From acba2c6b6385027882b1cb32553e1cca73c27109 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 8 Jul 2010 04:29:04 +0000 Subject: [PATCH] Rewrite VFR handling in Aegisub. Kill vfr.h and vfr.cpp and use the libaegisub versions of them instead. Rather than the globals VFR_Input and VFR_Output, everything related to frame rate is now part of the video context. Most things which used to use VFR_Output now call VideoContext::TimeAtFrame etc.; video providers, rather than modifying VFR_Input directly, now have getters for their frame rates which VideoContext calls. Read-only public access to VFR_Input and VFR_Output are still provided (hopefully temporarily) for a few things which were awkward to do through VideoContext. The Avisynth provider now might correctly handle VFR MKVs which can be opened with DirectShowSource but not DSS2. Rework keyframe handling as well, so that it continues to match the vfr handling in design and implementation. Originally committed to SVN as r4662. --- .../aegisub_vs2008/aegisub_vs2008.vcproj | 8 - aegisub/libaegisub/common/vfr.cpp | 9 +- aegisub/libaegisub/include/libaegisub/vfr.h | 4 - aegisub/src/Makefile.am | 1 - aegisub/src/ass_dialogue.cpp | 1 - aegisub/src/ass_file.cpp | 1 - aegisub/src/ass_time.cpp | 1 - aegisub/src/audio_display.cpp | 21 +- aegisub/src/audio_display.h | 19 - aegisub/src/auto4_lua.cpp | 9 +- aegisub/src/auto4_lua.h | 1 + aegisub/src/base_grid.cpp | 25 +- aegisub/src/base_grid.h | 11 +- aegisub/src/dialog_jumpto.cpp | 54 +- aegisub/src/dialog_shift_times.cpp | 5 +- aegisub/src/dialog_timing_processor.cpp | 87 +--- aegisub/src/dialog_timing_processor.h | 48 +- aegisub/src/dialog_video_details.cpp | 2 +- aegisub/src/export_framerate.cpp | 33 +- aegisub/src/export_framerate.h | 8 +- aegisub/src/export_visible_lines.cpp | 26 +- aegisub/src/frame_main.cpp | 68 +-- aegisub/src/frame_main.h | 1 - aegisub/src/frame_main_events.cpp | 181 ++++--- aegisub/src/include/aegisub/video_provider.h | 63 +-- aegisub/src/keyframe.cpp | 75 +-- aegisub/src/keyframe.h | 15 +- aegisub/src/main.cpp | 1 - aegisub/src/mkv_wrap.cpp | 53 +- aegisub/src/mkv_wrap.h | 14 +- aegisub/src/subs_edit_box.cpp | 5 +- aegisub/src/subs_grid.cpp | 49 +- aegisub/src/subs_grid.h | 12 - aegisub/src/subtitle_format.cpp | 65 +-- aegisub/src/subtitle_format.h | 17 - aegisub/src/subtitle_format_microdvd.cpp | 93 +--- aegisub/src/subtitle_format_microdvd.h | 8 - aegisub/src/subtitles_provider_csri.cpp | 23 +- aegisub/src/subtitles_provider_csri.h | 14 +- aegisub/src/timeedit_ctrl.cpp | 59 +-- aegisub/src/vfr.cpp | 393 --------------- aegisub/src/vfr.h | 142 ------ aegisub/src/video_box.cpp | 1 - aegisub/src/video_context.cpp | 470 ++++++------------ aegisub/src/video_context.h | 165 +++--- aegisub/src/video_display.cpp | 8 +- aegisub/src/video_provider_avs.cpp | 88 +--- aegisub/src/video_provider_avs.h | 103 +--- aegisub/src/video_provider_cache.cpp | 154 +----- aegisub/src/video_provider_cache.h | 59 +-- aegisub/src/video_provider_dummy.cpp | 81 --- aegisub/src/video_provider_dummy.h | 51 +- aegisub/src/video_provider_ffmpegsource.cpp | 74 +-- aegisub/src/video_provider_ffmpegsource.h | 41 +- aegisub/src/video_provider_manager.cpp | 5 +- aegisub/src/video_provider_quicktime.cpp | 106 +--- aegisub/src/video_provider_quicktime.h | 88 ++-- aegisub/src/video_provider_yuv4mpeg.cpp | 25 +- aegisub/src/video_provider_yuv4mpeg.h | 31 +- aegisub/src/video_slider.cpp | 17 +- aegisub/src/visual_tool.cpp | 1 - aegisub/src/visual_tool_drag.cpp | 3 +- 62 files changed, 680 insertions(+), 2616 deletions(-) delete mode 100644 aegisub/src/vfr.cpp delete mode 100644 aegisub/src/vfr.h diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj index 1af3f70ee..58346ac66 100644 --- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj +++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj @@ -1011,14 +1011,6 @@ RelativePath="..\..\src\vector2d.h" > - - - - const& timecodes) : timecodes(timecodes) { validate_timecodes(timecodes); - fps = timecodes.size() / (timecodes.back() / 1000.); + fps = (timecodes.size() - 1) * 1000. / (timecodes.back() - timecodes.front()); last = timecodes.back(); } @@ -202,10 +202,6 @@ Framerate &Framerate::operator=(double fps) { return *this = Framerate(fps); } -bool Framerate::operator==(Framerate const& right) const { - return fps == right.fps && timecodes == right.timecodes; -} - Framerate::Framerate(std::string const& filename) : fps(0.) { using namespace std; auto_ptr file(agi::io::Open(filename)); @@ -214,7 +210,8 @@ Framerate::Framerate(std::string const& filename) : fps(0.) { if (line == "# timecode format v2") { copy(line_iterator(*file, encoding), line_iterator(), back_inserter(timecodes)); validate_timecodes(timecodes); - fps = timecodes.size() / (timecodes.back() / 1000.); + fps = (timecodes.size() - 1) * 1000. / (timecodes.back() - timecodes.front()); + last = timecodes.back(); return; } if (line == "# timecode format v1" || line.substr(0, 7) == "Assume ") { diff --git a/aegisub/libaegisub/include/libaegisub/vfr.h b/aegisub/libaegisub/include/libaegisub/vfr.h index 046010b86..2aff1d1e5 100644 --- a/aegisub/libaegisub/include/libaegisub/vfr.h +++ b/aegisub/libaegisub/include/libaegisub/vfr.h @@ -132,10 +132,6 @@ public: bool IsVFR() const {return !timecodes.empty(); } bool IsLoaded() const { return !timecodes.empty() || fps; }; double FPS() const { return fps; } - - /// @brief Equality operator - /// @attention O(n) when both arguments are VFR - bool operator==(Framerate const& right) const; }; } diff --git a/aegisub/src/Makefile.am b/aegisub/src/Makefile.am index 9e87b6604..ba4c19e9c 100644 --- a/aegisub/src/Makefile.am +++ b/aegisub/src/Makefile.am @@ -302,7 +302,6 @@ aegisub_2_2_SOURCES = \ variable_data.cpp \ vector2d.cpp \ version.cpp \ - vfr.cpp \ video_box.cpp \ video_context.cpp \ video_display.cpp \ diff --git a/aegisub/src/ass_dialogue.cpp b/aegisub/src/ass_dialogue.cpp index ce848710d..6574bdc86 100644 --- a/aegisub/src/ass_dialogue.cpp +++ b/aegisub/src/ass_dialogue.cpp @@ -45,7 +45,6 @@ #include "ass_dialogue.h" #include "ass_override.h" #include "utils.h" -#include "vfr.h" AssDialogue::AssDialogue() : Comment(false) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index 7ab0cae88..b52b17176 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -60,7 +60,6 @@ #include "text_file_writer.h" #include "utils.h" #include "version.h" -#include "vfr.h" /// @brief AssFile constructor AssFile::AssFile () { diff --git a/aegisub/src/ass_time.cpp b/aegisub/src/ass_time.cpp index 23fdf9b95..5d7631ddb 100644 --- a/aegisub/src/ass_time.cpp +++ b/aegisub/src/ass_time.cpp @@ -50,7 +50,6 @@ #include "ass_time.h" #include "utils.h" -#include "vfr.h" /// @brief AssTime constructors diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 32c95061d..6c76f1ab2 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -65,7 +65,6 @@ #include "subs_grid.h" #include "timeedit_ctrl.h" #include "utils.h" -#include "vfr.h" #include "video_context.h" #ifdef __WXMAC__ @@ -295,7 +294,7 @@ void AudioDisplay::DoUpdateImage() { if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool()) { if (VideoContext::Get()->IsLoaded()) { dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Play Cursor")->GetColour()))); - int x = GetXAtMS(VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN())); + int x = GetXAtMS(VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN())); dc.DrawLine(x,0,x,h); } } @@ -477,19 +476,19 @@ void AudioDisplay::DrawInactiveLines(wxDC &dc) { /// @brief Draw keyframe markers /// @param dc The DC to draw to. void AudioDisplay::DrawKeyframes(wxDC &dc) { - wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); - int nKeys = (int)KeyFrames.Count(); + std::vector KeyFrames = VideoContext::Get()->GetKeyFrames(); + int nKeys = (int)KeyFrames.size(); dc.SetPen(wxPen(wxColour(255,0,255),1)); // Get min and max frames to care about - int minFrame = VFR_Output.GetFrameAtTime(GetMSAtX(0),true); - int maxFrame = VFR_Output.GetFrameAtTime(GetMSAtX(w),true); + int minFrame = VideoContext::Get()->FrameAtTime(GetMSAtX(0),agi::vfr::START); + int maxFrame = VideoContext::Get()->FrameAtTime(GetMSAtX(w),agi::vfr::END); // Scan list for (int i=0;i= minFrame && cur <= maxFrame) { - int x = GetXAtMS(VFR_Output.GetTimeAtFrame(cur,true)); + int x = GetXAtMS(VideoContext::Get()->TimeAtFrame(cur,agi::vfr::START)); dc.DrawLine(x,0,x,h); } else if (cur > maxFrame) break; @@ -1469,7 +1468,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) { if (middleClick) { SetFocus(); if (VideoContext::Get()->IsLoaded()) { - VideoContext::Get()->JumpToTime(GetMSAtX(x),true); + VideoContext::Get()->JumpToTime(GetMSAtX(x)); } } @@ -1719,13 +1718,13 @@ int AudioDisplay::GetBoundarySnap(int ms,int rangeX,bool shiftHeld,bool start) { if (shiftHeld) snapKey = !snapKey; if (snapKey && VideoContext::Get()->KeyFramesLoaded() && OPT_GET("Audio/Display/Draw/Keyframes")->GetBool()) { int64_t keyMS; - wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames(); + std::vector keyFrames = VideoContext::Get()->GetKeyFrames(); int frame; - for (unsigned int i=0;iTimeAtFrame(frame,start ? agi::vfr::START : agi::vfr::END); //if (start) keyX++; if (GetXAtMS(keyMS) >= 0 && GetXAtMS(keyMS) < w) boundaries.Add(keyMS); } diff --git a/aegisub/src/audio_display.h b/aegisub/src/audio_display.h index ab51d078e..9ea9c630d 100644 --- a/aegisub/src/audio_display.h +++ b/aegisub/src/audio_display.h @@ -34,12 +34,8 @@ /// @ingroup audio_ui /// - #pragma once - -/////////// -// Headers #ifndef AGI_PRE #include @@ -52,9 +48,6 @@ #include "audio_provider_manager.h" #include "audio_renderer_spectrum.h" - -////////////// -// Prototypes class AssDialogue; class StreamAudioProvider; class SubtitlesGrid; @@ -63,8 +56,6 @@ class AudioKaraoke; class VideoProvider; class FrameMain; - - /// DOCME /// @class AudioDisplay /// @brief DOCME @@ -83,11 +74,9 @@ private: /// DOCME AssDialogue *dialogue; - /// DOCME AudioSpectrum *spectrumRenderer; - /// DOCME wxBitmap *origImage; @@ -127,14 +116,12 @@ private: /// DOCME bool playingToEnd; - /// DOCME bool needImageUpdate; /// DOCME bool needImageUpdateWeak; - /// DOCME bool hasSel; @@ -186,14 +173,12 @@ private: /// DOCME int holdSyl; - /// DOCME int *peak; /// DOCME int *min; - /// DOCME int scrubTime; @@ -239,7 +224,6 @@ public: /// DOCME AudioPlayer *player; - /// DOCME bool NeedCommit; @@ -308,11 +292,8 @@ public: DECLARE_EVENT_TABLE() }; - /////// // IDs enum { - - /// DOCME Audio_Update_Timer = 1700 }; diff --git a/aegisub/src/auto4_lua.cpp b/aegisub/src/auto4_lua.cpp index f77dc4c7e..85b8c280a 100644 --- a/aegisub/src/auto4_lua.cpp +++ b/aegisub/src/auto4_lua.cpp @@ -64,7 +64,6 @@ #include "options.h" #include "standard_paths.h" #include "text_file_reader.h" -#include "vfr.h" #include "video_context.h" // This must be below the headers above. @@ -504,8 +503,8 @@ namespace Automation4 { { int ms = (int)lua_tonumber(L, -1); lua_pop(L, 1); - if (VFR_Output.IsLoaded()) { - lua_pushnumber(L, VFR_Output.GetFrameAtTime(ms, true)); + if (VideoContext::Get()->TimecodesLoaded()) { + lua_pushnumber(L, VideoContext::Get()->FrameAtTime(ms, agi::vfr::START)); return 1; } else { lua_pushnil(L); @@ -522,8 +521,8 @@ namespace Automation4 { { int frame = (int)lua_tonumber(L, -1); lua_pop(L, 1); - if (VFR_Output.IsLoaded()) { - lua_pushnumber(L, VFR_Output.GetTimeAtFrame(frame, true)); + if (VideoContext::Get()->TimecodesLoaded()) { + lua_pushnumber(L, VideoContext::Get()->TimeAtFrame(frame, agi::vfr::START)); return 1; } else { lua_pushnil(L); diff --git a/aegisub/src/auto4_lua.h b/aegisub/src/auto4_lua.h index 72bd71a0f..e1c2e9c37 100644 --- a/aegisub/src/auto4_lua.h +++ b/aegisub/src/auto4_lua.h @@ -53,6 +53,7 @@ #endif class wxWindow; +namespace agi { namespace vfr { class Framerate; } } /// DOCME diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index 600f5cc67..5527e512b 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -34,9 +34,6 @@ /// @ingroup main_ui /// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE @@ -56,7 +53,6 @@ #include "options.h" #include "subs_edit_box.h" #include "utils.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_slider.h" @@ -79,6 +75,7 @@ static inline void set_difference(const S1 &src1, const S2 &src2, D &dst) { /// BaseGrid::BaseGrid(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxWindow(parent, id, pos, size, style, name) +, context(VideoContext::Get()) { // Misc variables lastRow = -1; @@ -552,8 +549,8 @@ void BaseGrid::DrawImage(wxDC &dc) { strings.Add(wxString::Format(_T("%i"),curRow+1)); strings.Add(wxString::Format(_T("%i"),curDiag->Layer)); if (byFrame) { - strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true))); - strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),false))); + strings.Add(wxString::Format(_T("%i"),context->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START))); + strings.Add(wxString::Format(_T("%i"),context->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END))); } else { strings.Add(curDiag->Start.GetASSFormated()); @@ -787,7 +784,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) { // Normal click if ((click || dclick) && !shift && !ctrl && !alt) { SetActiveLine(dlg); - if (dclick) VideoContext::Get()->JumpToTime(dlg->Start.GetMS()); + if (dclick) context->JumpToTime(dlg->Start.GetMS()); SelectRow(row,false); parentFrame->UpdateToolbar(); lastRow = row; @@ -964,9 +961,9 @@ void BaseGrid::SetColumnWidths() { // Times if (byFrame) { - int tmp = VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true); + int tmp = context->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START); if (tmp > maxStart) maxStart = tmp; - tmp = VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),true); + tmp = context->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END); if (tmp > maxEnd) maxEnd = tmp; } } @@ -1053,8 +1050,8 @@ int BaseGrid::GetDialogueIndex(AssDialogue *diag) const { bool BaseGrid::IsDisplayed(AssDialogue *line) { VideoContext* con = VideoContext::Get(); if (!con->IsLoaded()) return false; - int f1 = VFR_Output.GetFrameAtTime(line->Start.GetMS(),true); - int f2 = VFR_Output.GetFrameAtTime(line->End.GetMS(),false); + int f1 = con->FrameAtTime(line->Start.GetMS(),agi::vfr::START); + int f2 = con->FrameAtTime(line->End.GetMS(),agi::vfr::END); if (f1 <= con->GetFrameN() && f2 >= con->GetFrameN()) return true; return false; } @@ -1106,7 +1103,7 @@ void BaseGrid::OnKeyPress(wxKeyEvent &event) { // Left/right, forward to seek bar if video is loaded if (key == WXK_LEFT || key == WXK_RIGHT) { - if (VideoContext::Get()->IsLoaded()) { + if (context->IsLoaded()) { parentFrame->videoBox->videoSlider->SetFocus(); parentFrame->videoBox->videoSlider->GetEventHandler()->ProcessEvent(event); return; @@ -1197,8 +1194,8 @@ void BaseGrid::OnKeyPress(wxKeyEvent &event) { } // Other events, send to audio display - if (VideoContext::Get()->audio->loaded) { - VideoContext::Get()->audio->GetEventHandler()->ProcessEvent(event); + if (context->audio->loaded) { + context->audio->GetEventHandler()->ProcessEvent(event); } else event.Skip(); } diff --git a/aegisub/src/base_grid.h b/aegisub/src/base_grid.h index 3f7256d7c..3e8ac2f61 100644 --- a/aegisub/src/base_grid.h +++ b/aegisub/src/base_grid.h @@ -37,8 +37,6 @@ #pragma once -//////////// -// Includes #ifndef AGI_PRE #include #include @@ -49,13 +47,11 @@ #include "selection_controller.h" - -////////////// -// Prototypes class AssEntry; class AssDialogue; class SubsEditBox; class FrameMain; +class VideoContext; /// DOCME typedef std::list::iterator entryIter; @@ -71,8 +67,6 @@ typedef SelectionListener SubtitleSelectionListener; /// /// DOCME class BaseGrid : public wxWindow, public BaseSelectionController { -private: - /// DOCME int lineHeight; @@ -120,11 +114,12 @@ protected: /// DOCME FrameMain *parentFrame; + VideoContext *context; + /// DOCME static const int columns = 10; bool showCol[columns]; - /// @brief DOCME /// @param alternate /// diff --git a/aegisub/src/dialog_jumpto.cpp b/aegisub/src/dialog_jumpto.cpp index 40334161f..c31a01acc 100644 --- a/aegisub/src/dialog_jumpto.cpp +++ b/aegisub/src/dialog_jumpto.cpp @@ -34,9 +34,6 @@ /// @ingroup secondary_ui /// - -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -50,36 +47,26 @@ #include "dialog_jumpto.h" #include "libresrc/libresrc.h" #include "utils.h" -#include "vfr.h" #include "video_context.h" - -/////// -// IDs +/// Event IDs enum { - - /// DOCME TEXT_JUMP_TIME = 1100, - - /// DOCME TEXT_JUMP_FRAME }; - - /// @brief Constructor /// @param parent /// DialogJumpTo::DialogJumpTo (wxWindow *parent) : wxDialog(parent, -1, _("Jump to"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS , _T("JumpTo")) { - // Set icon SetIcon(BitmapToIcon(GETIMAGE(jumpto_button_24))); // Set initial values ready = false; jumpframe = VideoContext::Get()->GetFrameN(); - jumptime.SetMS(VFR_Output.GetTimeAtFrame(jumpframe,true,true)); + jumptime.SetMS(VideoContext::Get()->TimeAtFrame(jumpframe)); wxString maxLength = wxString::Format(_T("%i"),VideoContext::Get()->GetLength()-1); // Times @@ -117,9 +104,6 @@ DialogJumpTo::DialogJumpTo (wxWindow *parent) ready = true; } - -/////////////// -// Event table BEGIN_EVENT_TABLE(DialogJumpTo, wxDialog) EVT_TEXT_ENTER(TEXT_JUMP_FRAME,DialogJumpTo::OnKey) EVT_TEXT_ENTER(TEXT_JUMP_TIME,DialogJumpTo::OnKey) @@ -129,42 +113,24 @@ BEGIN_EVENT_TABLE(DialogJumpTo, wxDialog) EVT_TEXT(TEXT_JUMP_FRAME, DialogJumpTo::OnEditFrame) END_EVENT_TABLE() - - -/// @brief Close -/// @param event -/// -void DialogJumpTo::OnCloseButton (wxCommandEvent &event) { OnClose(false); } - -/// @brief DOCME -/// @param event -/// -void DialogJumpTo::OnOK (wxCommandEvent &event) { OnClose(true); } - - +void DialogJumpTo::OnCloseButton (wxCommandEvent &) { OnClose(false); } +void DialogJumpTo::OnOK (wxCommandEvent &) { OnClose(true); } /// @brief On Key pressed -/// @param event -/// -void DialogJumpTo::OnKey(wxCommandEvent &event) { +void DialogJumpTo::OnKey(wxCommandEvent &) { EndModal(0); if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1; VideoContext::Get()->JumpToFrame(jumpframe); } - - /// @brief On OK button pressed /// @param ok -/// void DialogJumpTo::OnClose(bool ok) { EndModal(0); if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1; if (ok) VideoContext::Get()->JumpToFrame(jumpframe); } - - /// @brief Time editbox changed /// @param event /// @@ -173,10 +139,10 @@ void DialogJumpTo::OnEditTime (wxCommandEvent &event) { ready = false; // Update frame - long newframe = VFR_Output.GetFrameAtTime(JumpTime->time.GetMS()); + long newframe = VideoContext::Get()->FrameAtTime(JumpTime->time.GetMS()); if (jumpframe != newframe) { jumpframe = newframe; - JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe)); + JumpFrame->ChangeValue(wxString::Format(_T("%i"),jumpframe)); } ready = true; @@ -184,8 +150,6 @@ void DialogJumpTo::OnEditTime (wxCommandEvent &event) { else event.Skip(); } - - /// @brief Frame editbox changed /// @param event /// @@ -199,7 +163,7 @@ void DialogJumpTo::OnEditFrame (wxCommandEvent &event) { JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe)); // Update time - int newtime = VFR_Output.GetTimeAtFrame(jumpframe,true,true); + int newtime = VideoContext::Get()->TimeAtFrame(jumpframe); if (jumptime.GetMS() != newtime) { jumptime.SetMS(newtime); JumpTime->ChangeValue(jumptime.GetASSFormated()); @@ -209,5 +173,3 @@ void DialogJumpTo::OnEditFrame (wxCommandEvent &event) { } else event.Skip(); } - - diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp index 4a2043092..bdd28722b 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -61,10 +61,9 @@ #include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" -#include "vfr.h" +#include "video_context.h" #include "video_display.h" - /// @brief Constructor /// @param parent /// @param _grid @@ -92,7 +91,7 @@ DialogShiftTimes::DialogShiftTimes (wxWindow *parent,SubtitlesGrid *_grid) ShiftTime->SetToolTip(_("Enter time in h:mm:ss.cs notation")); RadioTime->SetToolTip(_("Shift by time")); ShiftFrame->Disable(); - if (!VFR_Output.IsLoaded()) RadioFrames->Disable(); + if (!VideoContext::Get()->TimecodesLoaded()) RadioFrames->Disable(); else { ShiftFrame->SetToolTip(_("Enter number of frames to shift by")); RadioFrames->SetToolTip(_("Shift by frames")); diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index 6abffcc22..d27cb3396 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -34,8 +34,6 @@ /// @ingroup tools_ui /// -//////////// -// Includes #include "config.h" #include "ass_dialogue.h" @@ -49,11 +47,20 @@ #include "subs_grid.h" #include "utils.h" #include "validators.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_display.h" +/// Window IDs +enum { + CHECK_ENABLE_LEADIN = 1850, + CHECK_ENABLE_LEADOUT, + CHECK_ENABLE_KEYFRAME, + CHECK_ENABLE_ADJASCENT, + BUTTON_SELECT_ALL, + BUTTON_SELECT_NONE, + TIMING_STYLE_LIST +}; /// @brief Constructor /// @param parent @@ -62,7 +69,6 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_grid) : wxDialog(parent,-1,_("Timing Post-Processor"),wxDefaultPosition,wxSize(400,250),wxDEFAULT_DIALOG_STYLE) { - // Set icon SetIcon(BitmapToIcon(GETIMAGE(timing_processor_toolbutton_24))); // Set variables @@ -75,7 +81,6 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr thresEndAfter = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key End After")->GetInt()); adjsThresTime = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt()); - // Styles box wxSizer *LeftSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Apply to styles")); wxArrayString styles = grid->ass->GetStyles(); @@ -201,12 +206,9 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr CenterOnParent(); - // Update UpdateControls(); } - - /// @brief Update controls /// void DialogTimingProcessor::UpdateControls() { @@ -237,9 +239,6 @@ void DialogTimingProcessor::UpdateControls() { ApplyButton->Enable(checked && (hasLeadIn->IsChecked() | hasLeadOut->IsChecked() | keysEnable->IsChecked() | adjsEnable->IsChecked())); } - -/////////////// -// Event table BEGIN_EVENT_TABLE(DialogTimingProcessor,wxDialog) EVT_CHECKBOX(CHECK_ENABLE_LEADIN,DialogTimingProcessor::OnCheckBox) EVT_CHECKBOX(CHECK_ENABLE_LEADOUT,DialogTimingProcessor::OnCheckBox) @@ -251,21 +250,11 @@ BEGIN_EVENT_TABLE(DialogTimingProcessor,wxDialog) EVT_BUTTON(BUTTON_SELECT_NONE,DialogTimingProcessor::OnSelectNone) END_EVENT_TABLE() - - -/// @brief Checkbox clicked -/// @param event -/// -void DialogTimingProcessor::OnCheckBox(wxCommandEvent &event) { +void DialogTimingProcessor::OnCheckBox(wxCommandEvent &) { UpdateControls(); } - - -/// @brief Select all styles -/// @param event -/// -void DialogTimingProcessor::OnSelectAll(wxCommandEvent &event) { +void DialogTimingProcessor::OnSelectAll(wxCommandEvent &) { size_t len = StyleList->GetCount(); for (size_t i=0;iCheck(i); @@ -273,12 +262,7 @@ void DialogTimingProcessor::OnSelectAll(wxCommandEvent &event) { UpdateControls(); } - - -/// @brief Unselect all styles -/// @param event -/// -void DialogTimingProcessor::OnSelectNone(wxCommandEvent &event) { +void DialogTimingProcessor::OnSelectNone(wxCommandEvent &) { size_t len = StyleList->GetCount(); for (size_t i=0;iCheck(i,false); @@ -286,12 +270,7 @@ void DialogTimingProcessor::OnSelectNone(wxCommandEvent &event) { UpdateControls(); } - - -/// @brief Apply button pressed -/// @param event -/// -void DialogTimingProcessor::OnApply(wxCommandEvent &event) { +void DialogTimingProcessor::OnApply(wxCommandEvent &) { // Save settings long temp = 0; leadIn->GetValue().ToLong(&temp); @@ -330,26 +309,16 @@ void DialogTimingProcessor::OnApply(wxCommandEvent &event) { } } - // Process if (valid) Process(); - - // Error message else wxMessageBox(wxString::Format(_("One of the lines in the file (%i) has negative duration. Aborting."),i),_("Invalid script"),wxICON_ERROR|wxOK); - // Close dialogue EndModal(0); } - - -/// @brief Get closest keyframe -/// @param frame -/// @return -/// int DialogTimingProcessor::GetClosestKeyFrame(int frame) { // Linear dumb search, not very efficient, but it doesn't really matter int closest = 0; - size_t n = KeyFrames.Count(); + size_t n = KeyFrames.size(); for (size_t i=0;iIsChecked()) { // Get keyframes - KeyFrames = VideoContext::Get()->GetKeyFrames(); - KeyFrames.Add(VideoContext::Get()->GetLength()-1); + VideoContext *con = VideoContext::Get(); + KeyFrames = con->GetKeyFrames(); + KeyFrames.push_back(con->GetLength()-1); // Variables int startF,endF; @@ -563,19 +524,19 @@ void DialogTimingProcessor::Process() { cur = GetSortedDialogue(i); // Get start/end frames - startF = VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true); - endF = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false); + startF = con->FrameAtTime(cur->Start.GetMS(),agi::vfr::START); + endF = con->FrameAtTime(cur->End.GetMS(),agi::vfr::END); // Get closest for start closest = GetClosestKeyFrame(startF); if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) { - cur->Start.SetMS(VFR_Output.GetTimeAtFrame(closest,true)); + cur->Start.SetMS(con->TimeAtFrame(closest,agi::vfr::START)); } // Get closest for end closest = GetClosestKeyFrame(endF)-1; if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) { - cur->End.SetMS(VFR_Output.GetTimeAtFrame(closest,false)); + cur->End.SetMS(con->TimeAtFrame(closest,agi::vfr::END)); } } } @@ -584,5 +545,3 @@ void DialogTimingProcessor::Process() { grid->ass->FlagAsModified(_("timing processor")); grid->CommitChanges(); } - - diff --git a/aegisub/src/dialog_timing_processor.h b/aegisub/src/dialog_timing_processor.h index 7badb386b..08aff2bb8 100644 --- a/aegisub/src/dialog_timing_processor.h +++ b/aegisub/src/dialog_timing_processor.h @@ -34,11 +34,6 @@ /// @ingroup tools_ui /// - - - -/////////// -// Headers #ifndef AGI_PRE #include @@ -51,33 +46,24 @@ #include #endif - -////////////// -// Prototypes class SubtitlesGrid; class AssDialogue; - - /// DOCME /// @class DialogTimingProcessor /// @brief DOCME /// /// DOCME class DialogTimingProcessor : public wxDialog { -private: - /// DOCME SubtitlesGrid *grid; /// DOCME wxStaticBoxSizer *KeyframesSizer; - /// DOCME wxCheckBox *onlySelection; - /// DOCME wxTextCtrl *leadIn; @@ -90,7 +76,6 @@ private: /// DOCME wxCheckBox *hasLeadOut; - /// DOCME wxCheckBox *keysEnable; @@ -106,7 +91,6 @@ private: /// DOCME wxTextCtrl *keysEndAfter; - /// DOCME wxCheckBox *adjsEnable; @@ -116,7 +100,6 @@ private: /// DOCME wxSlider *adjacentBias; - /// DOCME wxCheckListBox *StyleList; @@ -138,9 +121,8 @@ private: /// DOCME wxString leadInTime,leadOutTime,thresStartBefore,thresStartAfter,thresEndBefore,thresEndAfter,adjsThresTime; - /// DOCME - wxArrayInt KeyFrames; + std::vector KeyFrames; void OnCheckBox(wxCommandEvent &event); void OnSelectAll(wxCommandEvent &event); @@ -152,7 +134,6 @@ private: int GetClosestKeyFrame(int frame); bool StyleOK(wxString styleName); - /// DOCME std::vector Sorted; AssDialogue *GetSortedDialogue(int n); @@ -163,30 +144,3 @@ public: DECLARE_EVENT_TABLE() }; - - -/////// -// IDs -enum { - - /// DOCME - CHECK_ENABLE_LEADIN = 1850, - - /// DOCME - CHECK_ENABLE_LEADOUT, - - /// DOCME - CHECK_ENABLE_KEYFRAME, - - /// DOCME - CHECK_ENABLE_ADJASCENT, - - /// DOCME - BUTTON_SELECT_ALL, - - /// DOCME - BUTTON_SELECT_NONE, - - /// DOCME - TIMING_STYLE_LIST -}; diff --git a/aegisub/src/dialog_video_details.cpp b/aegisub/src/dialog_video_details.cpp index 24d79dedd..59e65dcb7 100644 --- a/aegisub/src/dialog_video_details.cpp +++ b/aegisub/src/dialog_video_details.cpp @@ -66,7 +66,7 @@ DialogVideoDetails::DialogVideoDetails(wxWindow *parent) int width = vprovider->GetWidth(); int height = vprovider->GetHeight(); int framecount = vprovider->GetFrameCount(); - double fps = vprovider->GetFPS(); + double fps = vprovider->GetFPS().FPS(); wxTextCtrl *fname_text = new wxTextCtrl(this, -1, VideoContext::Get()->videoName, wxDefaultPosition, wxSize(300,-1), wxTE_READONLY); wxTextCtrl *fps_text = new wxTextCtrl(this, -1, wxString::Format(_T("%.3f"), fps), wxDefaultPosition, wxDefaultSize, wxTE_READONLY); diff --git a/aegisub/src/export_framerate.cpp b/aegisub/src/export_framerate.cpp index 8321f4629..47e03a132 100644 --- a/aegisub/src/export_framerate.cpp +++ b/aegisub/src/export_framerate.cpp @@ -53,6 +53,7 @@ #include "ass_override.h" #include "export_framerate.h" #include "utils.h" +#include "video_context.h" /// DOCME /// @class LineData @@ -93,11 +94,13 @@ void AssTransformFramerateFilter::ProcessSubs(AssFile *subs, wxWindow *export_di wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) { wxWindow *base = new wxPanel(parent, -1); + LoadSettings(true); + // Input sizer wxSizer *InputSizer = new wxBoxSizer(wxHORIZONTAL); wxString initialInput; wxButton *FromVideo = new wxButton(base,Get_Input_From_Video,_("From Video")); - if (VFR_Input.IsLoaded()) initialInput = wxString::Format(_T("%2.3f"),VFR_Input.GetAverage()); + if (Input->IsLoaded()) initialInput = wxString::Format(_T("%2.3f"),Input->FPS()); else { initialInput = _T("23.976"); FromVideo->Enable(false); @@ -119,7 +122,7 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) { // Output bottom line RadioOutputCFR = new wxRadioButton(base,-1,_("Constant: ")); wxString initialOutput = initialInput; - if (VFR_Output.GetFrameRateType() != VFR) { + if (!Output->IsVFR()) { RadioOutputVFR->Enable(false); RadioOutputCFR->SetValue(true); } @@ -150,20 +153,20 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) { void AssTransformFramerateFilter::LoadSettings(bool IsDefault) { if (IsDefault) { - Input = &VFR_Input; - Output = &VFR_Output; + Input = &VideoContext::Get()->VFR_Input; + Output = &VideoContext::Get()->VFR_Output; } else { double temp; InputFramerate->GetValue().ToDouble(&temp); - t1.SetCFR(temp); + t1 = temp; Input = &t1; if (RadioOutputCFR->GetValue()) { OutputFramerate->GetValue().ToDouble(&temp); - t2.SetCFR(temp); + t2 = temp; Output = &t2; } - else Output = &VFR_Output; + else Output = &VideoContext::Get()->VFR_Output; if (Reverse->IsChecked()) { std::swap(Input, Output); @@ -215,7 +218,7 @@ void AssTransformFramerateFilter::TransformTimeTags (wxString name,int n,AssOver } void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { - if (!Input->IsLoaded() || !Output->IsLoaded() || Input == Output || *Input == *Output) return; + if (!Input->IsLoaded() || !Output->IsLoaded()) return; for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) { AssDialogue *curDialogue = dynamic_cast(*cur); @@ -225,7 +228,7 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { data.newK = 0; data.oldK = 0; data.newStart = trunc_cs(ConvertTime(curDialogue->Start.GetMS())); - data.newEnd = trunc_cs(ConvertTime(curDialogue->End.GetMS())); + data.newEnd = trunc_cs(ConvertTime(curDialogue->End.GetMS()) + 9); // Process stuff curDialogue->ParseASSTags(); @@ -239,16 +242,18 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { } int AssTransformFramerateFilter::ConvertTime(int time) { - int frame = Output->GetFrameAtTime(time, false); - int frameStart = Output->GetTimeAtFrame(frame, false, true); - int frameEnd = Output->GetTimeAtFrame(frame + 1, false, true); + int frame = Output->FrameAtTime(time); + int frameStart = Output->TimeAtFrame(frame); + int frameEnd = Output->TimeAtFrame(frame + 1); int frameDur = frameEnd - frameStart; double dist = double(time - frameStart) / frameDur; - int newStart = Input->GetTimeAtFrame(frame, false, true); - int newEnd = Input->GetTimeAtFrame(frame + 1, false, true); + int newStart = Input->TimeAtFrame(frame); + int newEnd = Input->TimeAtFrame(frame + 1); int newDur = newEnd - newStart; + int dongs = Input->FrameAtTime(newStart + newDur * dist, agi::vfr::END); + return newStart + newDur * dist; } diff --git a/aegisub/src/export_framerate.h b/aegisub/src/export_framerate.h index 2524b6528..5a6853952 100644 --- a/aegisub/src/export_framerate.h +++ b/aegisub/src/export_framerate.h @@ -35,7 +35,7 @@ /// #include "ass_export_filter.h" -#include "vfr.h" +#include class AssDialogue; class AssOverrideParameter; @@ -51,10 +51,10 @@ class AssTransformFramerateFilter : public AssExportFilter { static AssTransformFramerateFilter instance; // Yes, these are backwards - FrameRate *Input; /// Destination frame rate - FrameRate *Output; /// Source frame rate + const agi::vfr::Framerate *Input; /// Destination frame rate + const agi::vfr::Framerate *Output; /// Source frame rate - FrameRate t1,t2; + agi::vfr::Framerate t1,t2; wxTextCtrl *InputFramerate; /// Input frame rate text box wxTextCtrl *OutputFramerate; /// Output frame rate text box diff --git a/aegisub/src/export_visible_lines.cpp b/aegisub/src/export_visible_lines.cpp index 7e676d183..d0837b3d9 100644 --- a/aegisub/src/export_visible_lines.cpp +++ b/aegisub/src/export_visible_lines.cpp @@ -34,17 +34,13 @@ /// @ingroup export /// - -/////////// -// Headers #include "config.h" #include "ass_dialogue.h" #include "ass_file.h" #include "ass_override.h" #include "export_visible_lines.h" -#include "vfr.h" - +#include "video_context.h" /// @brief Constructor /// @@ -53,11 +49,6 @@ AssLimitToVisibleFilter::AssLimitToVisibleFilter() { frame = -1; } - - -/// @brief Init -/// @return -/// void AssLimitToVisibleFilter::Init() { if (initialized) return; initialized = true; @@ -67,15 +58,10 @@ void AssLimitToVisibleFilter::Init() { description = _("Limit to Visible Lines"); } - - /// @brief Process /// @param subs /// @param export_dialog -/// @return -/// void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) { - // Nothing to do if (frame == -1) return; AssDialogue *diag; @@ -86,8 +72,8 @@ void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog diag = dynamic_cast(*cur); if (diag) { // Invisible, remove frame - if (VFR_Output.GetFrameAtTime(diag->Start.GetMS(),true) > frame || - VFR_Output.GetFrameAtTime(diag->End.GetMS(),false) < frame) { + if (VideoContext::Get()->FrameAtTime(diag->Start.GetMS(),agi::vfr::START) > frame || + VideoContext::Get()->FrameAtTime(diag->End.GetMS(),agi::vfr::END) < frame) { delete *cur; subs->Line.erase(cur); @@ -96,8 +82,6 @@ void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog } } - - /// @brief Set limitation time /// @param _frame /// @@ -105,9 +89,5 @@ void AssLimitToVisibleFilter::SetFrame(int _frame) { instance.frame = _frame; } - - /// DOCME AssLimitToVisibleFilter AssLimitToVisibleFilter::instance; - - diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index c2b8a77f8..eccd5a0d5 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -79,7 +79,6 @@ #include "text_file_writer.h" #include "utils.h" #include "version.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_display.h" @@ -642,6 +641,7 @@ void FrameMain::DeInitContents() { AssFile::StackReset(); delete AssFile::top; HelpButton::ClearPages(); + VideoContext::Get()->audio = NULL; } /// @brief Update toolbar @@ -760,6 +760,8 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) { // Update title bar UpdateTitle(); + + VideoContext::Get()->Refresh(); } /// @brief Save subtitles @@ -949,7 +951,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) { int autoLoadMode = OPT_GET("App/Auto/Load Linked Files")->GetInt(); bool hasToLoad = false; if (curSubsAudio != audioBox->audioName || - curSubsVFR != VFR_Output.GetFilename() || + curSubsVFR != VideoContext::Get()->GetTimecodesName() || curSubsVideo != VideoContext::Get()->videoName || curSubsKeyframes != VideoContext::Get()->GetKeyFramesName() #ifdef WITH_AUTOMATION @@ -970,25 +972,18 @@ void FrameMain::SynchronizeProject(bool fromSubs) { } if (doLoad) { - // Variable frame rate - LoadVFR(curSubsVFR); - // Video if (curSubsVideo != VideoContext::Get()->videoName) { - //if (curSubsVideo != _T("")) { LoadVideo(curSubsVideo); if (VideoContext::Get()->IsLoaded()) { VideoContext::Get()->SetAspectRatio(videoAr,videoArValue); videoBox->videoDisplay->SetZoom(videoZoom); VideoContext::Get()->JumpToFrame(videoPos); } - //} } - // Keyframes - if (curSubsKeyframes != _T("")) { - KeyFrameFile::Load(curSubsKeyframes); - } + VideoContext::Get()->LoadTimecodes(curSubsVFR); + VideoContext::Get()->LoadKeyframes(curSubsKeyframes); // Audio if (curSubsAudio != audioBox->audioName) { @@ -1058,7 +1053,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) { subs->SetScriptInfo(_T("Video Aspect Ratio"),ar); subs->SetScriptInfo(_T("Video Zoom Percent"),zoom); subs->SetScriptInfo(_T("Video Position"),seekpos); - subs->SetScriptInfo(_T("VFR File"),MakeRelativePath(VFR_Output.GetFilename(),AssFile::top->filename)); + subs->SetScriptInfo(_T("VFR File"),MakeRelativePath(VideoContext::Get()->GetTimecodesName(),AssFile::top->filename)); subs->SetScriptInfo(_T("Keyframes File"),MakeRelativePath(VideoContext::Get()->GetKeyFramesName(),AssFile::top->filename)); // Store Automation script data @@ -1104,26 +1099,11 @@ void FrameMain::SynchronizeProject(bool fromSubs) { void FrameMain::LoadVideo(wxString file,bool autoload) { if (blockVideoLoad) return; Freeze(); - VideoContext::Get()->Stop(); try { - if (VideoContext::Get()->IsLoaded()) { - if (VFR_Output.GetFrameRateType() == VFR) { - if (!autoload) { - int result = wxMessageBox(_("You have timecodes loaded currently. Would you like to unload them?"), _("Unload timecodes?"), wxYES_NO, this); - if (result == wxYES) { - VFR_Output.Unload(); - } - } - } - else { - VFR_Output.Unload(); - } - } VideoContext::Get()->SetVideo(file); } catch (const wchar_t *error) { - wxString err(error); - wxMessageBox(err, _T("Error opening video file"), wxOK | wxICON_ERROR, this); + wxMessageBox(error, _T("Error opening video file"), wxOK | wxICON_ERROR, this); } catch (...) { wxMessageBox(_T("Unknown error"), _T("Error opening video file"), wxOK | wxICON_ERROR, this); @@ -1199,43 +1179,17 @@ void FrameMain::LoadAudio(wxString filename,bool FromVideo) { } } -/// @brief Loads VFR -/// @param filename void FrameMain::LoadVFR(wxString filename) { - VideoContext::Get()->Stop(); - if (filename != _T("")) { - try { - VFR_Output.Load(filename); - SubsGrid->Refresh(false); - } - - // Fail - catch (const wchar_t *error) { - wxString err(error); - wxMessageBox(err, _T("Error opening timecodes file"), wxOK | wxICON_ERROR, this); - } - catch (...) { - wxMessageBox(_T("Unknown error"), _T("Error opening timecodes file"), wxOK | wxICON_ERROR, this); - } + if (filename.empty()) { + VideoContext::Get()->CloseTimecodes(); } - else { - VFR_Output.Unload(); - if (VideoContext::Get()->IsLoaded() && !VFR_Output.IsLoaded()) { - VFR_Output.SetCFR(VideoContext::Get()->GetFPS()); - } + VideoContext::Get()->LoadTimecodes(filename); } - SubsGrid->CommitChanges(); EditBox->UpdateFrameTiming(); } -/// @brief Saves VFR -/// @param filename -void FrameMain::SaveVFR(wxString filename) { - VFR_Output.Save(filename); -} - /// @brief Open help void FrameMain::OpenHelp(wxString) { HelpButton::OpenPage(_T("Main")); diff --git a/aegisub/src/frame_main.h b/aegisub/src/frame_main.h index 98dc3c0e5..8b99921c9 100644 --- a/aegisub/src/frame_main.h +++ b/aegisub/src/frame_main.h @@ -315,7 +315,6 @@ private: void LoadVideo(wxString filename,bool autoload=false); void LoadAudio(wxString filename,bool FromVideo=false); void LoadVFR(wxString filename); - void SaveVFR(wxString filename); void LoadSubtitles(wxString filename,wxString charset=_T("")); bool SaveSubtitles(bool saveas=false,bool withCharset=false); int TryToCloseSubs(bool enableCancel=true); diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp index a8d7cdce4..baf014d06 100644 --- a/aegisub/src/frame_main_events.cpp +++ b/aegisub/src/frame_main_events.cpp @@ -89,7 +89,6 @@ #include "subs_grid.h" #include "toggle_bitmap.h" #include "utils.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_display.h" @@ -336,8 +335,8 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { MenuBar->Enable(Menu_Video_AR_235,attached); MenuBar->Enable(Menu_Video_AR_Custom,attached); MenuBar->Enable(Menu_Video_Detach,state); - MenuBar->Enable(Menu_File_Save_VFR,VFR_Output.GetFrameRateType() == VFR); - MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.GetFrameRateType() == VFR); + MenuBar->Enable(Menu_File_Save_VFR,VideoContext::Get()->TimecodesLoaded()); + MenuBar->Enable(Menu_File_Close_VFR,VideoContext::Get()->OverTimecodesLoaded()); MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded()); MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded()); MenuBar->Enable(Menu_Video_Details,state); @@ -399,7 +398,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { MenuBar->Enable(Menu_Subtitles_Insert,state); state = count > 0 && continuous; MenuBar->Enable(MENU_DUPLICATE,state); - state = count > 0 && continuous && VFR_Output.IsLoaded(); + state = count > 0 && continuous && VideoContext::Get()->TimecodesLoaded(); MenuBar->Enable(MENU_DUPLICATE_NEXT_FRAME,state); state = count == 2; MenuBar->Enable(MENU_SWAP,state); @@ -540,7 +539,7 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) { /// @param event void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) { int number = event.GetId()-Menu_Keyframes_Recent; - KeyFrameFile::Load(lagi_wxString(config::mru->GetEntry("Keyframes", number))); + VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", number))); videoBox->videoSlider->Refresh(); audioBox->audioDisplay->Update(); Refresh(); @@ -789,7 +788,7 @@ void FrameMain::OnSaveVFR(wxCommandEvent &) { + _("All Files") + _T(" (*.*)|*.*"); wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (!filename.empty()) { - SaveVFR(filename); + VideoContext::Get()->SaveTimecodes(filename); OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); } } @@ -797,19 +796,26 @@ void FrameMain::OnSaveVFR(wxCommandEvent &) { /// @brief Close VFR tags void FrameMain::OnCloseVFR(wxCommandEvent &) { - LoadVFR(_T("")); + LoadVFR(""); } /// @brief Open keyframes void FrameMain::OnOpenKeyframes (wxCommandEvent &) { // Pick file wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); - wxString filename = wxFileSelector(_T("Select the keyframes file to open"),path,_T(""),_T(".txt"),_T("All supported formats (*.txt, *.pass, *.stats, *.log)|*.txt;*.pass;*.stats;*.log|All files (*.*)|*.*"),wxFD_FILE_MUST_EXIST | wxFD_OPEN); - if (filename.IsEmpty()) return; + wxString filename = wxFileSelector( + _T("Select the keyframes file to open"), + path, + _T("") + ,_T(".txt"), + _T("All supported formats (*.txt, *.pass, *.stats, *.log)|*.txt;*.pass;*.stats;*.log|All files (*.*)|*.*"), + wxFD_FILE_MUST_EXIST | wxFD_OPEN); + + if (filename.empty()) return; OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); // Load - KeyFrameFile::Load(filename); + VideoContext::Get()->LoadKeyframes(filename); videoBox->videoSlider->Refresh(); audioBox->audioDisplay->Update(); Refresh(); @@ -817,7 +823,7 @@ void FrameMain::OnOpenKeyframes (wxCommandEvent &) { /// @brief Close keyframes void FrameMain::OnCloseKeyframes (wxCommandEvent &) { - VideoContext::Get()->CloseOverKeyFrames(); + VideoContext::Get()->CloseKeyframes(); videoBox->videoSlider->Refresh(); audioBox->audioDisplay->Update(); Refresh(); @@ -831,8 +837,7 @@ void FrameMain::OnSaveKeyframes (wxCommandEvent &) { if (filename.IsEmpty()) return; OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); - // Save - KeyFrameFile::Save(filename); + VideoContext::Get()->SaveKeyframes(filename); } /// @brief Zoom levels @@ -1064,118 +1069,100 @@ void FrameMain::OnAutomationMacro (wxCommandEvent &event) { /// @brief Snap subs to video void FrameMain::OnSnapSubsStartToVid (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) { - SubsGrid->SetSubsToVideo(true); - } + SubsGrid->SetSubsToVideo(true); } - /// @brief DOCME void FrameMain::OnSnapSubsEndToVid (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) { - SubsGrid->SetSubsToVideo(false); - } + SubsGrid->SetSubsToVideo(false); } /// @brief Jump video to subs void FrameMain::OnSnapVidToSubsStart (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) { - SubsGrid->SetVideoToSubs(true); - } + SubsGrid->SetVideoToSubs(true); } /// @brief DOCME void FrameMain::OnSnapVidToSubsEnd (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) { - SubsGrid->SetVideoToSubs(false); - } + SubsGrid->SetVideoToSubs(false); } /// @brief Snap to scene void FrameMain::OnSnapToScene (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded()) { - // Get frames - wxArrayInt sel = SubsGrid->GetSelection(); - int curFrame = VideoContext::Get()->GetFrameN(); - int prev = 0; - int next = 0; - int frame = 0; - wxArrayInt keyframes = VideoContext::Get()->GetKeyFrames(); - size_t n = keyframes.Count(); - bool found = false; - for (size_t i=0;iIsLoaded() || !con->KeyFramesLoaded()) return; - if (frame == curFrame) { - prev = frame; - if (i < n-1) next = keyframes[i+1]; - else next = VideoContext::Get()->GetLength(); - found = true; - break; - } + // Get frames + wxArrayInt sel = SubsGrid->GetSelection(); + int curFrame = con->GetFrameN(); + int prev = 0; + int next = 0; - if (frame > curFrame) { - if (i != 0) prev = keyframes[i-1]; - else prev = 0; - next = frame; - found = true; - break; - } - } - - // Last section? - if (!found) { - if (n > 0) prev = keyframes[n-1]; - else prev = 0; - next = VideoContext::Get()->GetLength(); - } - - // Get times - int start_ms = VFR_Output.GetTimeAtFrame(prev,true); - int end_ms = VFR_Output.GetTimeAtFrame(next-1,false); - AssDialogue *cur; - - // Update rows - for (size_t i=0;iGetDialogue(sel[i]); - cur->Start.SetMS(start_ms); - cur->End.SetMS(end_ms); - } - - // Commit - SubsGrid->editBox->Update(true); - SubsGrid->ass->FlagAsModified(_("snap to scene")); - SubsGrid->CommitChanges(); + const std::vector &keyframes = con->GetKeyFrames(); + if (curFrame < keyframes.front()) { + next = keyframes.front(); } + else if (curFrame >= keyframes.back()) { + prev = keyframes.back(); + next = con->GetLength(); + } + else { + std::vector::const_iterator kf = std::lower_bound(keyframes.begin(), keyframes.end(), curFrame); + if (*kf == curFrame) { + prev = *kf; + next = *(kf + 1); + } + else { + prev = *(kf - 1); + next = *kf; + } + } + + // Get times + int start_ms = con->TimeAtFrame(prev,agi::vfr::START); + int end_ms = con->TimeAtFrame(next-1,agi::vfr::END); + AssDialogue *cur; + + // Update rows + for (size_t i=0;iGetDialogue(sel[i]); + cur->Start.SetMS(start_ms); + cur->End.SetMS(end_ms); + } + + // Commit + SubsGrid->editBox->Update(true); + SubsGrid->ass->FlagAsModified(_("snap to scene")); + SubsGrid->CommitChanges(); } /// @brief Shift to frame void FrameMain::OnShiftToFrame (wxCommandEvent &) { - if (VideoContext::Get()->IsLoaded()) { - wxArrayInt sels = SubsGrid->GetSelection(); - size_t n=sels.Count(); - if (n == 0) return; + if (!VideoContext::Get()->IsLoaded()) return; - // Get shifting in ms - AssDialogue *cur = SubsGrid->GetDialogue(sels[0]); - if (!cur) return; - int shiftBy = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),true) - cur->Start.GetMS(); + wxArrayInt sels = SubsGrid->GetSelection(); + size_t n=sels.Count(); + if (n == 0) return; - // Update - for (size_t i=0;iGetDialogue(sels[i]); - if (cur) { - cur->Start.SetMS(cur->Start.GetMS()+shiftBy); - cur->End.SetMS(cur->End.GetMS()+shiftBy); - } + // Get shifting in ms + AssDialogue *cur = SubsGrid->GetDialogue(sels[0]); + if (!cur) return; + int shiftBy = VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN(),agi::vfr::START) - cur->Start.GetMS(); + + // Update + for (size_t i=0;iGetDialogue(sels[i]); + if (cur) { + cur->Start.SetMS(cur->Start.GetMS()+shiftBy); + cur->End.SetMS(cur->End.GetMS()+shiftBy); } - - // Commit - SubsGrid->ass->FlagAsModified(_("shift to frame")); - SubsGrid->CommitChanges(); - SubsGrid->editBox->Update(true,false); } + + // Commit + SubsGrid->ass->FlagAsModified(_("shift to frame")); + SubsGrid->CommitChanges(); + SubsGrid->editBox->Update(true,false); } /// @brief Undo diff --git a/aegisub/src/include/aegisub/video_provider.h b/aegisub/src/include/aegisub/video_provider.h index 185e8df1c..f01b0a10c 100644 --- a/aegisub/src/include/aegisub/video_provider.h +++ b/aegisub/src/include/aegisub/video_provider.h @@ -34,16 +34,10 @@ /// @ingroup main_headers video_input /// - #pragma once - -////////// -// Headers -#include "aegisub.h" -#include "vfr.h" #include "video_frame.h" - +#include /// @class VideoProvider /// @brief DOCME @@ -51,62 +45,31 @@ /// DOCME class VideoProvider { public: - - /// @brief // Virtual destructor - /// @return - /// virtual ~VideoProvider() {} // Override this method to actually get frames virtual const AegiVideoFrame GetFrame(int n)=0; // Override the following methods to get video information: - virtual int GetPosition()=0; // Get the number of the last frame loaded - virtual int GetFrameCount()=0; // Get total number of frames - virtual int GetWidth()=0; // Returns the video width in pixels - virtual int GetHeight()=0; // Returns the video height in pixels - virtual double GetFPS()=0; // Get framerate in frames per second - virtual bool AreKeyFramesLoaded()=0; // Returns true if keyframe info is loaded, false otherwise - virtual bool IsVFR()=0; // Returns true if video is VFR - virtual wxArrayInt GetKeyFrames()=0; // Returns list of keyframes - virtual FrameRate GetTrueFrameRate()=0; // Returns magic VFR stuff + virtual int GetPosition() const=0; ///< Get the number of the last frame loaded + virtual int GetFrameCount() const=0; ///< Get total number of frames + virtual int GetWidth() const=0; ///< Returns the video width in pixels + virtual int GetHeight() const=0; ///< Returns the video height in pixels + virtual agi::vfr::Framerate GetFPS() const=0; ///< Get frame rate + virtual std::vector GetKeyFrames() const=0;///< Returns list of keyframes - /// @brief // Use this to set any post-loading warnings, such as "being loaded with unreliable seeking" - /// @return - /// - virtual wxString GetWarning() { return L""; } - - - /// @brief // Name of decoder, e.g. "Avisynth/FFMpegSource" - /// @return - /// - virtual wxString GetDecoderName() { return L"Unknown"; } + /// @brief Use this to set any post-loading warnings, such as "being loaded with unreliable seeking" + virtual wxString GetWarning() const { return L""; } + /// @brief Name of decoder, e.g. "Avisynth/FFMpegSource" + virtual wxString GetDecoderName() const = 0; /// @brief Does this provider want Aegisub to cache video frames? /// @return Returns true if caching is desired, false otherwise. - virtual bool WantsCaching() { return false; } - - - /// @brief // For "special" providers that don't deal well with VFR (i.e. Avisynth) - /// @return - /// - virtual bool NeedsVFRHack() { return false; }; // Returns true if provider needs special VFR treatment - - /// @brief DOCME - /// @return - /// - virtual bool IsNativelyByFrames() { return true; }; - - /// @brief DOCME - /// @param list - /// - virtual void OverrideFrameTimeList(std::vector list) {} // Override the list with the provided one, for VFR handling + virtual bool WantsCaching() const { return false; } }; - - /// @class VideoProviderFactory /// @brief DOCME /// @@ -119,5 +82,3 @@ public: virtual ~VideoProviderFactory() {} virtual VideoProvider *CreateProvider(wxString video)=0; }; - - diff --git a/aegisub/src/keyframe.cpp b/aegisub/src/keyframe.cpp index 4eb1b590d..1a8252b1e 100644 --- a/aegisub/src/keyframe.cpp +++ b/aegisub/src/keyframe.cpp @@ -34,8 +34,6 @@ /// @ingroup video_input /// -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -48,19 +46,11 @@ #include "options.h" #include "text_file_reader.h" #include "text_file_writer.h" -#include "vfr.h" #include "video_context.h" - -/// @brief Load Keyframes -/// @param filename -/// -void KeyFrameFile::Load(wxString filename) { - // Load +std::vector KeyFrameFile::Load(wxString filename) { try { - // Open file - wxArrayInt keyFrames; - keyFrames.Empty(); + std::vector keyFrames; TextFileReader file(filename,_T("ASCII")); wxString cur = file.ReadLineFromFile(); @@ -71,53 +61,36 @@ void KeyFrameFile::Load(wxString filename) { else if (cur.StartsWith(_T("#options:"))) { Openx264KeyFrames(file, keyFrames); } else { throw(_T("Invalid or unsupported keyframes file.")); } - // Set keyframes - VideoContext::Get()->SetOverKeyFrames(keyFrames); - VideoContext::Get()->SetKeyFramesName(filename); - - // Add to recent config::mru->Add("Keyframes", STD_STR(filename)); + return keyFrames; } // Fail catch (const wchar_t *error) { - wxString err(error); - wxMessageBox(err, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); + wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); } catch (...) { wxMessageBox(_T("Unknown error"), _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); } + return std::vector(); } - - -/// @brief Save Keyframes -/// @param filename -/// -void KeyFrameFile::Save(wxString filename) { - // Get keyframes - wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames(); - - // Write header +void KeyFrameFile::Save(wxString filename, std::vector const& keyFrames) { TextFileWriter file(filename,_T("ASCII")); file.WriteLineToFile(_T("# keyframe format v1")); - file.WriteLineToFile(wxString::Format(_T("fps %f"),VideoContext::Get()->GetFPS())); + file.WriteLineToFile(wxString::Format(_T("fps %f"),VideoContext::Get()->VFR_Input.FPS())); - // Write keyframes - for (unsigned int i=0;iAdd("Keyframes", STD_STR(filename)); } - - /// @brief Aegisub keyframes file /// @param file /// @param keyFrames /// -void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) +void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, std::vector& keyFrames) { double fps; wxString cur = file.ReadLineFromFile(); @@ -129,10 +102,8 @@ void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames if (fps == 0.0) throw _T("Invalid FPS."); // Set FPS - if (!VideoContext::Get()->IsLoaded()) { - VideoContext::Get()->SetFPS(fps); - VFR_Input.SetCFR(fps); - if (!VFR_Output.IsLoaded()) VFR_Output.SetCFR(fps); + if (!VideoContext::Get()->TimecodesLoaded()) { + VideoContext::Get()->ovrFPS = fps; } // Read lines @@ -141,26 +112,24 @@ void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames if (!cur.IsEmpty() && !cur.StartsWith(_T("#")) && cur.IsNumber()) { long temp; cur.ToLong(&temp); - keyFrames.Add(temp); + keyFrames.push_back(temp); } - } + } } - - /// @brief XviD stats file /// @param file /// @param keyFrames /// -void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) +void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, std::vector& keyFrames) { wxString cur = file.ReadLineFromFile(); unsigned int count = 0; // Read lines while (file.HasMoreLines()) { - if (cur.StartsWith(_T("i"))) { - keyFrames.Add(count); + if (cur.StartsWith(_T("i"))) { + keyFrames.push_back(count); count++; } else if (cur.StartsWith(_T("p")) || cur.StartsWith(_T("b"))) { @@ -170,12 +139,11 @@ void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames } } - /// @brief DivX stats file /// @param file /// @param keyFrames /// -void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) +void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, std::vector& keyFrames) { wxString cur = file.ReadLineFromFile(); unsigned int count = 0; @@ -184,7 +152,7 @@ void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames while (file.HasMoreLines()) { if (cur.Contains(_T("I"))) { - keyFrames.Add(count); + keyFrames.push_back(count); count++; } else if (cur.Contains(_T("P")) || cur.Contains(_T("B"))) { @@ -194,12 +162,11 @@ void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames } } - /// @brief x264 stats file /// @param file /// @param keyFrames /// -void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames) +void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, std::vector& keyFrames) { wxString cur = file.ReadLineFromFile(); unsigned int count = 0; @@ -210,7 +177,7 @@ void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames { pos = cur.Find(_T("type:")); if (cur.Mid(pos,6).Right(1).Lower() == (_T("i"))) { - keyFrames.Add(count); + keyFrames.push_back(count); count++; } else if (cur.Mid(pos,6).Right(1).Lower() == (_T("p")) || cur.Mid(pos,6).Right(1).Lower() == (_T("b"))) { @@ -219,5 +186,3 @@ void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames cur = file.ReadLineFromFile(); } } - - diff --git a/aegisub/src/keyframe.h b/aegisub/src/keyframe.h index c8f146690..82af544da 100644 --- a/aegisub/src/keyframe.h +++ b/aegisub/src/keyframe.h @@ -34,9 +34,6 @@ /// @ingroup video_input /// - -/////////// -// Headers #include "text_file_reader.h" @@ -48,13 +45,13 @@ class KeyFrameFile { public: - static void Load(wxString filename); - static void Save(wxString filename); + static std::vector Load(wxString filename); + static void Save(wxString filename, std::vector const& keyframes); private: - static void OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); - static void OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); - static void OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); - static void Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames); + static void OpenAegiKeyFrames(TextFileReader& file, std::vector& keyFrames); + static void OpenXviDKeyFrames(TextFileReader& file, std::vector& keyFrames); + static void OpenDivXKeyFrames(TextFileReader& file, std::vector& keyFrames); + static void Openx264KeyFrames(TextFileReader& file, std::vector& keyFrames); }; diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index f6d6ebc1d..f08b032d5 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -280,7 +280,6 @@ bool AegisubApp::OnInit() { /// int AegisubApp::OnExit() { SubtitleFormat::DestroyFormats(); - VideoContext::Clear(); delete plugins; delete config::opt; delete config::mru; diff --git a/aegisub/src/mkv_wrap.cpp b/aegisub/src/mkv_wrap.cpp index bb91a7193..885371f48 100644 --- a/aegisub/src/mkv_wrap.cpp +++ b/aegisub/src/mkv_wrap.cpp @@ -34,9 +34,6 @@ /// @ingroup video_input /// - -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -44,6 +41,7 @@ #include #include +#include #include #include @@ -53,6 +51,7 @@ #include "ass_file.h" #include "ass_time.h" #include "dialog_progress.h" +#include #include "mkv_wrap.h" @@ -259,51 +258,21 @@ void MatroskaWrapper::Parse() { } +static int mkv_round(double num) { + return (int)(num + .5); +} /// @brief Set target to timecodes /// @param target /// @return /// -void MatroskaWrapper::SetToTimecodes(FrameRate &target) { - // Enough frames? - int frames = timecodes.size(); - if (frames <= 1) return; +void MatroskaWrapper::SetToTimecodes(agi::vfr::Framerate &target) { + if (timecodes.size() <= 1) return; - // Sort - //std::sort::iterator>(timecodes.begin(),timecodes.end()); - - // Check if it's CFR - /* - bool isCFR = true; - double estimateCFR = timecodes.back() / (timecodes.size()-1); - double t1,t2; - for (int i=1;i 2) { - isCFR = false; - break; - } - } - */ - bool isCFR = false; - double estimateCFR = 0; - - // Constant framerate - if (isCFR) { - estimateCFR = 1/estimateCFR * 1000.0; - if (fabs(estimateCFR - 24000.0/1001.0) < 0.02) estimateCFR = 24000.0 / 1001.0; - if (fabs(estimateCFR - 30000.0/1001.0) < 0.02) estimateCFR = 30000.0 / 1001.0; - target.SetCFR(estimateCFR); - } - - // Variable framerate - else { - std::vector times; - for (int i=0;i times; + times.reserve(timecodes.size()); + std::transform(timecodes.begin(), timecodes.end(), std::back_inserter(times), &mkv_round); + target = agi::vfr::Framerate(times); } diff --git a/aegisub/src/mkv_wrap.h b/aegisub/src/mkv_wrap.h index 062ceecc6..369d576ab 100644 --- a/aegisub/src/mkv_wrap.h +++ b/aegisub/src/mkv_wrap.h @@ -34,11 +34,6 @@ /// @ingroup video_input /// - - - -/////////// -// Headers #ifndef AGI_PRE #include #include @@ -48,14 +43,9 @@ #endif #include "MatroskaParser.h" -#include "vfr.h" - -////////////// -// Prototypes class AssFile; - - +namespace agi { namespace vfr { class Framerate; } } /// DOCME /// @class MkvStdIO @@ -161,7 +151,7 @@ public: void Close(); void Parse(); - void SetToTimecodes(FrameRate &target); + void SetToTimecodes(agi::vfr::Framerate &target); /// @brief DOCME /// @return diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 063d20238..9c243dd40 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -299,9 +299,6 @@ void SubsEditBox::Update (bool timeOnly,bool weak) { // Audio if (!weak) audio->SetDialogue(grid,curdiag,grid->GetDialogueIndex(curdiag)); - // Video - VideoContext::Get()->curLine = curdiag; - TextEdit->EmptyUndoBuffer(); } else enabled = false; @@ -550,7 +547,7 @@ void SubsEditBox::SetControlsState (bool state) { /// @brief Disables or enables frame timing /// void SubsEditBox::UpdateFrameTiming () { - if (VideoContext::Get()->IsLoaded()) ByFrame->Enable(enabled); + if (VideoContext::Get()->TimecodesLoaded()) ByFrame->Enable(enabled); else { ByFrame->Enable(false); ByTime->SetValue(true); diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index a985465dc..09b7b5718 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -34,9 +34,6 @@ /// @ingroup main_ui /// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE @@ -61,13 +58,9 @@ #include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" -#include "vfr.h" #include "video_context.h" #include "video_display.h" - -/////////////// -// Event table BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid) EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown) EVT_MENU(MENU_SWAP,SubtitlesGrid::OnSwap) @@ -171,14 +164,14 @@ void SubtitlesGrid::OnPopupMenu(bool alternate) { state = (sels == 1); menu.Append(MENU_INSERT_BEFORE,_("&Insert (before)"),_T("Inserts a line before current"))->Enable(state); menu.Append(MENU_INSERT_AFTER,_("Insert (after)"),_T("Inserts a line after current"))->Enable(state); - state = (sels == 1 && VideoContext::Get()->IsLoaded()); + state = (sels == 1 && context->IsLoaded()); menu.Append(MENU_INSERT_BEFORE_VIDEO,_("Insert at video time (before)"),_T("Inserts a line after current, starting at video time"))->Enable(state); menu.Append(MENU_INSERT_AFTER_VIDEO,_("Insert at video time (after)"),_T("Inserts a line after current, starting at video time"))->Enable(state); menu.AppendSeparator(); // Duplicate selection menu.Append(MENU_DUPLICATE,_("&Duplicate"),_("Duplicate the selected lines"))->Enable(continuous); - menu.Append(MENU_DUPLICATE_NEXT_FRAME,_("&Duplicate and shift by 1 frame"),_("Duplicate lines and shift by one frame"))->Enable(continuous && VFR_Output.IsLoaded()); + menu.Append(MENU_DUPLICATE_NEXT_FRAME,_("&Duplicate and shift by 1 frame"),_("Duplicate lines and shift by one frame"))->Enable(continuous && context->TimecodesLoaded()); menu.Append(MENU_SPLIT_BY_KARAOKE,_("Split (by karaoke)"),_("Uses karaoke timing to split line into multiple smaller lines"))->Enable(sels > 0); // Swaps selection @@ -318,7 +311,7 @@ void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) { } // Duplicate and shift - if (VFR_Output.IsLoaded()) { + if (context->TimecodesLoaded()) { if (Hotkeys.IsPressed(_T("Grid duplicate and shift one frame"))) { DuplicateLines(n,n2,true); return; @@ -518,7 +511,7 @@ void SubtitlesGrid::OnInsertBeforeVideo (wxCommandEvent &event) { // Create line to add AssDialogue *def = new AssDialogue; - int video_ms = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),true); + int video_ms = context->TimeAtFrame(context->GetFrameN(),agi::vfr::START); def->Start.SetMS(video_ms); def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt()); def->Style = GetDialogue(n)->Style; @@ -542,7 +535,7 @@ void SubtitlesGrid::OnInsertAfterVideo (wxCommandEvent &event) { // Create line to add AssDialogue *def = new AssDialogue; - int video_ms = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),true); + int video_ms = context->TimeAtFrame(context->GetFrameN(),agi::vfr::START); def->Start.SetMS(video_ms); def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt()); def->Style = GetDialogue(n)->Style; @@ -819,7 +812,6 @@ void SubtitlesGrid::ClearMaps() { void SubtitlesGrid::UpdateMaps() { BeginBatch(); - VideoContext::Get()->curLine = NULL; line_iter_map.clear(); BaseGrid::ClearMaps(); @@ -1244,9 +1236,9 @@ void SubtitlesGrid::DuplicateLines(int n1,int n2,bool nextFrame) { // Shift to next frame if (nextFrame) { - int posFrame = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false) + 1; - cur->Start.SetMS(VFR_Output.GetTimeAtFrame(posFrame,true)); - cur->End.SetMS(VFR_Output.GetTimeAtFrame(posFrame,false)); + int posFrame = context->FrameAtTime(cur->End.GetMS(),agi::vfr::END) + 1; + cur->Start.SetMS(context->TimeAtFrame(posFrame,agi::vfr::START)); + cur->End.SetMS(context->TimeAtFrame(posFrame,agi::vfr::END)); } // Insert @@ -1292,8 +1284,8 @@ void SubtitlesGrid::ShiftLineByTime(int n,int len,int type) { void SubtitlesGrid::ShiftLineByFrames(int n,int len,int type) { AssDialogue *cur = GetDialogue(n); - if (type != 2) cur->Start.SetMS(VFR_Output.GetTimeAtFrame(len + VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true),true)); - if (type != 1) cur->End.SetMS(VFR_Output.GetTimeAtFrame(len + VFR_Output.GetFrameAtTime(cur->End.GetMS(),false),false)); + if (type != 2) cur->Start.SetMS(context->TimeAtFrame(len + context->FrameAtTime(cur->Start.GetMS(),agi::vfr::START),agi::vfr::START)); + if (type != 1) cur->End.SetMS(context->TimeAtFrame(len + context->FrameAtTime(cur->End.GetMS(),agi::vfr::END),agi::vfr::END)); } @@ -1394,19 +1386,19 @@ bool SubtitlesGrid::SplitLineByKaraoke(int lineNumber) { /// @param videoOnly /// void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) { - if (VideoContext::Get()->IsLoaded() || force) { + if (context->IsLoaded() || force) { // Check if it's playing bool playing = false; - if (VideoContext::Get()->IsPlaying()) { + if (context->IsPlaying()) { playing = true; - VideoContext::Get()->Stop(); + context->Stop(); } // Update video - if (VideoContext::Get()->IsLoaded()) VideoContext::Get()->Refresh(); + if (context->IsLoaded()) context->Refresh(); // Resume play - if (playing) VideoContext::Get()->Play(); + if (playing) context->Play(); } if (!videoOnly) { @@ -1422,18 +1414,15 @@ void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) { } } - - /// @brief Set start to video pos /// @param start /// @return /// void SubtitlesGrid::SetSubsToVideo(bool start) { - // Check if it's OK to do it - if (!VFR_Output.IsLoaded()) return; + if (!context->IsLoaded()) return; // Get new time - int ms = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),start); + int ms = context->TimeAtFrame(context->GetFrameN(),start ? agi::vfr::START : agi::vfr::END); // Update selection wxArrayInt sel = GetSelection(); @@ -1468,9 +1457,9 @@ void SubtitlesGrid::SetVideoToSubs(bool start) { AssDialogue *cur = GetDialogue(sel[0]); if (cur) { if (start) - VideoContext::Get()->JumpToTime(cur->Start.GetMS()); + context->JumpToTime(cur->Start.GetMS()); else - VideoContext::Get()->JumpToFrame(VFR_Output.GetFrameAtTime(cur->End.GetMS(),false)); + context->JumpToTime(cur->End.GetMS(), agi::vfr::END); } } diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index 5c8b27c41..adc94c4de 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -34,11 +34,6 @@ /// @ingroup main_ui /// - - - -//////////// -// Includes #ifndef AGI_PRE #include #include @@ -54,9 +49,6 @@ #include "audio_provider_manager.h" #include "base_grid.h" - -////////////// -// Prototypes class AssFile; class AssEntry; class AssDialogue; @@ -64,13 +56,9 @@ class SubsEditBox; class FrameMain; class AudioDisplay; - - /// DOCME typedef std::list::iterator entryIter; - - /// DOCME /// @class SubtitlesGrid /// @brief DOCME diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index 2aca78da6..b0b0c8259 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -34,9 +34,6 @@ /// @ingroup subtitle_io /// - -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -55,8 +52,7 @@ #include "subtitle_format_transtation.h" #include "subtitle_format_ttxt.h" #include "subtitle_format_txt.h" -#include "vfr.h" - +#include "video_context.h" /// @brief Constructor /// @@ -66,24 +62,18 @@ SubtitleFormat::SubtitleFormat() { isCopy = false; } - - /// @brief Destructor /// SubtitleFormat::~SubtitleFormat () { Remove(); } - - /// DOCME std::list SubtitleFormat::formats; /// DOCME bool SubtitleFormat::loaded = false; - - /// @brief Set target /// @param file /// @@ -94,8 +84,6 @@ void SubtitleFormat::SetTarget(AssFile *file) { assFile = file; } - - /// @brief Create copy /// void SubtitleFormat::CreateCopy() { @@ -103,8 +91,6 @@ void SubtitleFormat::CreateCopy() { isCopy = true; } - - /// @brief Clear copy /// void SubtitleFormat::ClearCopy() { @@ -115,16 +101,12 @@ void SubtitleFormat::ClearCopy() { } } - - /// @brief Clear subtitles /// void SubtitleFormat::Clear() { assFile->Clear(); } - - /// @brief Load default /// @param defline /// @@ -132,8 +114,6 @@ void SubtitleFormat::LoadDefault(bool defline) { assFile->LoadDefault(defline); } - - /// @brief Add line /// @param data /// @param group @@ -143,8 +123,6 @@ void SubtitleFormat::AddLine(wxString data,wxString group,int &version,wxString assFile->AddLine(data,group,version,outgroup); } - - /// @brief Add formats /// void SubtitleFormat::LoadFormats () { @@ -164,8 +142,6 @@ void SubtitleFormat::LoadFormats () { loaded = true; } - - /// @brief Destroy formats /// void SubtitleFormat::DestroyFormats () { @@ -176,8 +152,6 @@ void SubtitleFormat::DestroyFormats () { formats.clear(); } - - /// @brief Get an appropriate reader /// @param filename /// @return @@ -193,8 +167,6 @@ SubtitleFormat *SubtitleFormat::GetReader(wxString filename) { return NULL; } - - /// @brief Get an appropriate writer /// @param filename /// @return @@ -210,8 +182,6 @@ SubtitleFormat *SubtitleFormat::GetWriter(wxString filename) { return NULL; } - - /// @brief Register /// @return /// @@ -223,8 +193,6 @@ void SubtitleFormat::Register() { formats.push_back(this); } - - /// @brief Remove /// @return /// @@ -238,8 +206,6 @@ void SubtitleFormat::Remove() { } } - - /// @brief Get read wildcards /// @return /// @@ -247,8 +213,6 @@ wxArrayString SubtitleFormat::GetReadWildcards() { return wxArrayString(); } - - /// @brief Get write wildcards /// @return /// @@ -256,8 +220,6 @@ wxArrayString SubtitleFormat::GetWriteWildcards() { return wxArrayString(); } - - /// @brief Get wildcard list /// @param mode /// @return @@ -313,8 +275,6 @@ wxString SubtitleFormat::GetWildcards(int mode) { return final; } - - /// @brief Ask the user to enter the FPS /// @param showSMPTE /// @return @@ -325,11 +285,12 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) { fps_rat.smpte_dropframe = false; // ensure it's false by default // Video FPS - bool vidLoaded = VFR_Output.IsLoaded(); + VideoContext *context = VideoContext::Get(); + bool vidLoaded = context->TimecodesLoaded(); if (vidLoaded) { wxString vidFPS; - if (VFR_Output.GetFrameRateType() == VFR) vidFPS = _T("VFR"); - else vidFPS = wxString::Format(_T("%.3f"),VFR_Output.GetAverage()); + if (context->FPS().IsVFR()) vidFPS = _T("VFR"); + else vidFPS = wxString::Format(_T("%.3f"),context->FPS().FPS()); choices.Add(wxString::Format(_T("From video (%s)"),vidFPS.c_str())); } @@ -403,16 +364,12 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) { return fps_rat; } - - /// @brief Sort lines /// void SubtitleFormat::SortLines() { AssFile::Sort(*Line); } - - /// @brief Convert tags /// @param format /// @param lineEnd @@ -438,8 +395,6 @@ void SubtitleFormat::ConvertTags(int format,const wxString &lineEnd,bool mergeLi } } - - /// @brief Remove all comment lines /// void SubtitleFormat::StripComments() { @@ -458,8 +413,6 @@ void SubtitleFormat::StripComments() { } } - - /// @brief Remove all non-dialogue lines /// void SubtitleFormat::StripNonDialogue() { @@ -477,8 +430,6 @@ void SubtitleFormat::StripNonDialogue() { } } - - /// @brief Helper function for RecombineOverlaps() /// @param list /// @param next @@ -501,7 +452,6 @@ static void InsertLineSortedIntoList(std::list &list, std::list @@ -49,22 +45,15 @@ #include - -////////////// -// Prototypes class AssFile; class AssEntry; - - /// DOCME /// @class SubtitleFormat /// @brief DOCME /// /// DOCME class SubtitleFormat { -private: - /// DOCME bool isCopy; @@ -74,7 +63,6 @@ private: void Register(); void Remove(); - /// DOCME static std::list formats; @@ -82,7 +70,6 @@ private: static bool loaded; protected: - /// DOCME struct FPSRational { @@ -96,7 +83,6 @@ protected: bool smpte_dropframe; }; - /// DOCME std::list *Line; @@ -131,7 +117,6 @@ public: static wxString GetWildcards(int mode); - /// @brief DOCME /// @param filename /// @return @@ -162,6 +147,4 @@ public: static void DestroyFormats(); }; - DEFINE_SIMPLE_EXCEPTION(SubtitleFormatParseError, agi::InvalidInputException, "subtitle_io/parse/generic") - diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index 98c585304..e62f28373 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -34,9 +34,6 @@ /// @ingroup subtitle_io /// - -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -48,42 +45,22 @@ #include "subtitle_format_microdvd.h" #include "text_file_reader.h" #include "text_file_writer.h" -#include "vfr.h" +#include "video_context.h" - -/// @brief Get format name -/// @return -/// wxString MicroDVDSubtitleFormat::GetName() { return _T("MicroDVD"); } - - -/// @brief Get read wildcards -/// @return -/// wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() { wxArrayString formats; formats.Add(_T("sub")); return formats; } - - -/// @brief Get write wildcards -/// @return -/// wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() { return GetReadWildcards(); } - - -/// @brief Can read a file? -/// @param filename -/// @return -/// bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) { // Return false immediately if extension is wrong if (filename.Right(4).Lower() != _T(".sub")) return false; @@ -98,43 +75,25 @@ bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) { return false; } - - -/// @brief Can write a file? -/// @param filename -/// @return -/// bool MicroDVDSubtitleFormat::CanWriteFile(wxString filename) { return (filename.Right(4).Lower() == _T(".sub")); } - - -/// @brief Read a file -/// @param filename -/// @param forceEncoding -/// @return -/// void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) { - // Load and prepare regexp TextFileReader file(filename); wxRegEx exp(_T("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$"),wxRE_ADVANCED); - // Load default LoadDefault(false); - // Prepare conversion - FrameRate cfr; - FrameRate *rate = 𝔠 + agi::vfr::Framerate cfr; + const agi::vfr::Framerate *rate = 𝔠 - // Loop bool isFirst = true; FPSRational fps_rat; double fps = 0.0; while (file.HasMoreLines()) { wxString line = file.ReadLineFromFile(); if (exp.Matches(line)) { - // Parse long f1,f2; exp.GetMatch(line,1).ToLong(&f1); exp.GetMatch(line,2).ToLong(&f2); @@ -147,7 +106,7 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) try { text.ToDouble(&fps); } - catch (...) {} + catch (...) { } } isFirst = false; @@ -155,24 +114,22 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) if (fps <= 0.0) { fps_rat = AskForFPS(); if (fps_rat.num == 0) return; - else if (fps_rat.num > 0) cfr.SetCFR(double(fps_rat.num)/double(fps_rat.den)); - else rate = &VFR_Output; + else if (fps_rat.num > 0) cfr = double(fps_rat.num)/fps_rat.den; + else rate = &VideoContext::Get()->FPS(); } else { - cfr.SetCFR(fps); + cfr = fps; continue; } } // Start and end times int start,end; - start = rate->GetTimeAtFrame(f1,true); - end = rate->GetTimeAtFrame(f2,false); + start = rate->TimeAtFrame(f1,agi::vfr::START); + end = rate->TimeAtFrame(f2,agi::vfr::END); - // Process text text.Replace(_T("|"),_T("\\N")); - // Create and insert line AssDialogue *line = new AssDialogue(); line->group = _T("[Events]"); line->Style = _T("Default"); @@ -184,21 +141,15 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) } } - - -/// @brief Write a file -/// @param filename -/// @param encoding -/// void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { - // Set FPS - FrameRate cfr; - FrameRate *rate = 𝔠 + agi::vfr::Framerate cfr; + const agi::vfr::Framerate *rate = 𝔠 + FPSRational fps_rat = AskForFPS(); if (fps_rat.num == 0 || fps_rat.den == 0) return; - double fps = double(fps_rat.num) / double(fps_rat.den); - if (fps > 0.0) cfr.SetCFR(fps); - else rate = &VFR_Output; + double fps = double(fps_rat.num) / fps_rat.den; + if (fps > 0.0) cfr = fps; + else rate = &VideoContext::Get()->FPS(); // Convert file CreateCopy(); @@ -208,12 +159,11 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { MergeIdentical(); ConvertTags(1,_T("|")); - // Open file TextFileWriter file(filename,encoding); // Write FPS line - if (rate->GetFrameRateType() != VFR) { - file.WriteLineToFile(wxString::Format(_T("{1}{1}%.6f"),rate->GetAverage())); + if (!rate->IsVFR()) { + file.WriteLineToFile(wxString::Format(_T("{1}{1}%.6f"),rate->FPS())); } // Write lines @@ -221,17 +171,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { for (list::iterator cur=Line->begin();cur!=Line->end();cur++) { AssDialogue *current = dynamic_cast(*cur); if (current && !current->Comment) { - // Prepare data - int start = rate->GetFrameAtTime(current->Start.GetMS(),true); - int end = rate->GetFrameAtTime(current->End.GetMS(),false); + int start = rate->FrameAtTime(current->Start.GetMS(),agi::vfr::START); + int end = rate->FrameAtTime(current->End.GetMS(),agi::vfr::END); - // Write data file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,current->Text.c_str())); } } - // Clean up ClearCopy(); } - - diff --git a/aegisub/src/subtitle_format_microdvd.h b/aegisub/src/subtitle_format_microdvd.h index 4da8eeea6..5bf20b36a 100644 --- a/aegisub/src/subtitle_format_microdvd.h +++ b/aegisub/src/subtitle_format_microdvd.h @@ -34,14 +34,8 @@ /// @ingroup subtitle_io /// - - - -/////////// -// Headers #include "subtitle_format.h" - /// DOCME /// @class MicroDVDSubtitleFormat /// @brief DOCME @@ -59,5 +53,3 @@ public: bool CanWriteFile(wxString filename); void WriteFile(wxString filename,wxString encoding); }; - - diff --git a/aegisub/src/subtitles_provider_csri.cpp b/aegisub/src/subtitles_provider_csri.cpp index 433451dab..16aa654a3 100644 --- a/aegisub/src/subtitles_provider_csri.cpp +++ b/aegisub/src/subtitles_provider_csri.cpp @@ -47,7 +47,6 @@ #include "text_file_writer.h" #include "video_context.h" - /// @brief Constructor /// @param type /// @@ -56,17 +55,14 @@ CSRISubtitlesProvider::CSRISubtitlesProvider(wxString type) { instance = NULL; } - - /// @brief Destructor /// CSRISubtitlesProvider::~CSRISubtitlesProvider() { + if (!tempfile.empty()) wxRemoveFile(tempfile); if (instance) csri_close(instance); instance = NULL; } - - /// @brief Load subtitles /// @param subs /// @@ -108,14 +104,16 @@ void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs) { // Open from disk else { - wxString subsFileName = VideoContext::Get()->GetTempWorkFile(); - subs->Save(subsFileName,false,false,wxSTRING_ENCODING); - instance = csri_open_file(renderer,subsFileName.mb_str(wxConvUTF8),NULL); + if (tempfile.empty()) { + tempfile = wxFileName::CreateTempFileName(_T("aegisub")); + wxRemoveFile(tempfile); + tempfile += L".ass"; + } + subs->Save(tempfile,false,false,wxSTRING_ENCODING); + instance = csri_open_file(renderer,tempfile.utf8_str(),NULL); } } - - /// @brief Draw subtitles /// @param dst /// @param time @@ -155,8 +153,6 @@ void CSRISubtitlesProvider::DrawSubtitles(AegiVideoFrame &dst,double time) { csri_render(instance,&frame,time); } - - /// @brief Get CSRI subtypes /// wxArrayString CSRISubtitlesProviderFactory::GetSubTypes() { @@ -179,7 +175,4 @@ wxArrayString CSRISubtitlesProviderFactory::GetSubTypes() { return final; } - #endif // WITH_CSRI - - diff --git a/aegisub/src/subtitles_provider_csri.h b/aegisub/src/subtitles_provider_csri.h index 4577a0d40..ddc954bd9 100644 --- a/aegisub/src/subtitles_provider_csri.h +++ b/aegisub/src/subtitles_provider_csri.h @@ -34,15 +34,10 @@ /// @ingroup subtitle_rendering /// - -/////////// -// Headers - #ifdef WITH_CSRI #include "include/aegisub/subtitles_provider.h" #ifdef WIN32 - /// DOCME #define CSRIAPI #endif @@ -53,21 +48,19 @@ #include #endif - /// DOCME /// @class CSRISubtitlesProvider /// @brief DOCME /// /// DOCME class CSRISubtitlesProvider : public SubtitlesProvider { -private: - /// DOCME wxString subType; /// DOCME csri_inst *instance; + wxString tempfile; public: CSRISubtitlesProvider(wxString subType); ~CSRISubtitlesProvider(); @@ -76,8 +69,6 @@ public: void DrawSubtitles(AegiVideoFrame &dst,double time); }; - - /// DOCME /// @class CSRISubtitlesProviderFactory /// @brief DOCME @@ -85,7 +76,6 @@ public: /// DOCME class CSRISubtitlesProviderFactory : public SubtitlesProviderFactory { public: - /// @brief DOCME /// @param subType /// @@ -94,5 +84,3 @@ public: }; #endif - - diff --git a/aegisub/src/timeedit_ctrl.cpp b/aegisub/src/timeedit_ctrl.cpp index e1b9e13b7..203b574fd 100644 --- a/aegisub/src/timeedit_ctrl.cpp +++ b/aegisub/src/timeedit_ctrl.cpp @@ -34,9 +34,6 @@ /// @ingroup custom_control /// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE @@ -51,8 +48,7 @@ #include "main.h" #include "options.h" #include "timeedit_ctrl.h" -#include "vfr.h" - +#include "video_context.h" #ifdef __WXGTK__ /// Use the multiline style only on wxGTK to workaround some wxGTK bugs with the default singleline style. @@ -63,7 +59,6 @@ #define TimeEditWindowStyle wxTE_CENTRE #endif - /// @brief Constructor /// @param parent /// @param id @@ -114,9 +109,6 @@ wxTextCtrl(parent,id,value,pos,size,TimeEditWindowStyle | style,validator,name) Connect(wxEVT_KILL_FOCUS,wxFocusEventHandler(TimeEdit::OnKillFocus)); } - -/////////////// -// Event table BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl) EVT_MOUSE_EVENTS(TimeEdit::OnMouseEvent) EVT_KEY_DOWN(TimeEdit::OnKeyDown) @@ -124,30 +116,20 @@ BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl) EVT_MENU(Time_Edit_Paste,TimeEdit::OnPaste) END_EVENT_TABLE() - - /// @brief Modified event /// @param event -/// @return -/// void TimeEdit::OnModified(wxCommandEvent &event) { event.Skip(); if (!ready) return; Modified(); } - - /// @brief Modified function /// @param byUser -/// @return -/// void TimeEdit::Modified(bool byUser) { - // Lock if (!ready) return; ready = false; - // Update if (byFrame) Update(); else UpdateTime(byUser); @@ -156,13 +138,9 @@ void TimeEdit::Modified(bool byUser) { SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour())); } modified = true; - - // Done ready = true; } - - /// @brief Set time and update stuff /// @param ms /// @param setModified @@ -174,18 +152,14 @@ void TimeEdit::SetTime(int ms,bool setModified) { if (setModified && oldMs != ms) Modified(false); } - - /// @brief Toggles between set by frame and time /// @param enable -/// @return -/// void TimeEdit::SetByFrame(bool enable) { if (enable == byFrame) return; // By frames if (enable) { - if (VFR_Output.IsLoaded()) { + if (VideoContext::Get()->IsLoaded()) { byFrame = true; UpdateText(); } @@ -198,22 +172,18 @@ void TimeEdit::SetByFrame(bool enable) { } } - - /// @brief Update text to reflect time value /// void TimeEdit::UpdateText() { ready = false; if (byFrame) { - int frame_n = VFR_Output.GetFrameAtTime(time.GetMS(),!isEnd); + int frame_n = VideoContext::Get()->FrameAtTime(time.GetMS(),isEnd ? agi::vfr::END : agi::vfr::START); SetValue(wxString::Format(_T("%i"),frame_n)); } else SetValue(time.GetASSFormated()); ready = true; } - - /// @brief Update /// void TimeEdit::Update() { @@ -221,7 +191,7 @@ void TimeEdit::Update() { if (byFrame) { long temp; GetValue().ToLong(&temp); - time.SetMS(VFR_Output.GetTimeAtFrame(temp,!isEnd)); + time.SetMS(VideoContext::Get()->TimeAtFrame(temp,isEnd ? agi::vfr::END : agi::vfr::START)); } // Update time if not on insertion mode @@ -238,8 +208,6 @@ void TimeEdit::Update() { modified = false; } - - /// @brief Reads value from a text control and update it /// @param byUser /// @@ -273,8 +241,6 @@ void TimeEdit::UpdateTime(bool byUser) { } } - - /// @brief Key pressed /// @param event /// @@ -316,8 +282,6 @@ void TimeEdit::OnKeyDown(wxKeyEvent &event) { } } - - /// @brief Focus lost /// @param event /// @@ -331,14 +295,10 @@ void TimeEdit::OnKillFocus(wxFocusEvent &event) { event.Skip(); } - ///// Mouse/copy/paste events down here ///// - /// @brief Mouse event /// @param event -/// @return -/// void TimeEdit::OnMouseEvent(wxMouseEvent &event) { // Right click context menu if (event.RightUp()) { @@ -355,8 +315,6 @@ void TimeEdit::OnMouseEvent(wxMouseEvent &event) { event.Skip(); } - - /// @brief Menu Copy /// @param event /// @@ -367,8 +325,6 @@ void TimeEdit::OnCopy(wxCommandEvent &event) { Refresh(); } - - /// @brief Menu Paste /// @param event /// @@ -378,10 +334,7 @@ void TimeEdit::OnPaste(wxCommandEvent &event) { Refresh(); } - - /// @brief Copy to clipboard -/// @return /// void TimeEdit::CopyTime() { // Frame @@ -397,8 +350,6 @@ void TimeEdit::CopyTime() { } } - - /// @brief Paste from clipboard /// void TimeEdit::PasteTime() { @@ -432,5 +383,3 @@ void TimeEdit::PasteTime() { } } } - - diff --git a/aegisub/src/vfr.cpp b/aegisub/src/vfr.cpp deleted file mode 100644 index f128c99e0..000000000 --- a/aegisub/src/vfr.cpp +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Aegisub Project http://www.aegisub.org/ -// -// $Id$ - -/// @file vfr.cpp -/// @brief Handle variable frame rate files -/// @ingroup video_input -/// - -#include "config.h" - -#ifndef AGI_PRE -#include -#endif - -#include "compat.h" -#include "main.h" -#include "options.h" -#include "text_file_reader.h" -#include "text_file_writer.h" -#include "utils.h" -#include "vfr.h" - - -/// @brief V2 Clear function -void FrameRate::Clear () { - Frame.clear(); -} - -/// @brief V2 Add frame -/// @param ms -void FrameRate::AddFrame(int ms) { - Frame.push_back(ms); -} - -/// @brief V2 Get Average -void FrameRate::CalcAverage() { - if (Frame.size() <= 1) - throw _("No timecodes to average"); - - AverageFrameRate = double(Frame.back()) / (Frame.size()-1); -} - -/// @brief Constructor -FrameRate::FrameRate() { - Unload(); -} - -/// @brief Destructor -FrameRate::~FrameRate() { - Unload(); -} - -/// @brief Loads VFR file -/// @param filename -void FrameRate::Load(wxString filename) { - using namespace std; - - Unload(); - - // Check if file exists - wxFileName filetest(filename); - if (!filetest.FileExists()) throw _T("File not found."); - - // Open file - TextFileReader file(filename); - - try { - // Read header - wxString curLine; - curLine = file.ReadLineFromFile(); - wxString header = curLine; - bool first = (header.Left(7).Lower() == _T("assume ")); - - // V1, code converted from avcvfr9 - if (header == _T("# timecode format v1") || first) { - // Locate the default fps line - do { - // Get next line - if (!first) curLine = file.ReadLineFromFile(); - first = false; - - // Skip empty lines and comments - if (curLine == _T("") || curLine.Left(1) == _T("#")) continue; - - else if (curLine.Left(7).Lower() != _T("assume ")) throw _T("Encountered data before 'Assume ' line"); - else { - if (!curLine.Mid(6).ToDouble(&AverageFrameRate) || AverageFrameRate <= 0) throw _T("Invalid 'Assume ' line"); - break; - } - } while (file.HasMoreLines()); - - // Read and expand all timecodes to v2 - wxString curline; - - double currenttime = 0; - int lposition = -1; - - long lstart; - long lend; - double lfps; - - while (file.HasMoreLines()) { - curLine = file.ReadLineFromFile(); - - // Skip empty lines and comments - if (curLine == _T("") || curLine.Left(1) == _T("#")) - continue; - - wxString tmp = curLine.AfterFirst(_T(',')); - wxString temp = curLine.BeforeFirst(_T(',')); - if (!temp.ToLong(&lstart) || lstart < 0) - throw _T("Timecode parsing error, invalid start format found"); - temp = tmp.BeforeLast(_T(',')); - if (!temp.ToLong(&lend) || lend < 0) - throw _T("Timecode parsing error, invalid end format found"); - temp = tmp.AfterLast(_T(',')); - if (!temp.ToDouble(&lfps) || lfps <= 0) - throw _T("Timecode parsing error, invalid fps format found"); - - if (lstart <= lposition) - throw _T("Timecode parsing error, out of order or overlapping timecode range found"); - - - for (int i = 0; i <= lstart - lposition - 2; i++) - AddFrame((int)(floor(currenttime+(i*1000) / AverageFrameRate))); - - currenttime += ((lstart - lposition - 1)*1000) / AverageFrameRate; - - for (int i = 0; i <= lend - lstart; i++) - AddFrame((int)(floor(currenttime+(i*1000) / lfps))); - - currenttime += ((lend - lstart + 1)*1000) / lfps; - - lposition = lend; - } - - AddFrame(currenttime); - last_time = currenttime; - last_frame = (int)Frame.size() - 1; - } - - // V2 - else if (header == _T("# timecode format v2")) { - // Assigns new VFR file - FrameRateType = VFR; - - long lftime = -1; - long cftime = 0; - last_frame = 0; - - // Reads body - while (file.HasMoreLines()) { - curLine = file.ReadLineFromFile(); - - //skip empty lines and comments - if (curLine == _T("") || curLine.Left(1) == _T("#")) - continue; - - wxString tmp = curLine.BeforeFirst(_T('.')); - tmp.ToLong(&cftime); - - if (lftime >= cftime) - throw _T("Out of order/too close timecodes found"); - - AddFrame(cftime); - lftime = cftime; - } - - last_time = cftime; - last_frame = (int)Frame.size() - 1; - - CalcAverage(); - - } - - // Unknown - else { - throw _T("Unknown time code file format."); - } - - } - catch (...) { - Unload(); - throw; - } - - // Close file - loaded = true; - vfrFile = filename; - FrameRateType = VFR; - - // Add to recent - config::mru->Add("Timecodes", STD_STR(filename)); -} - -/// @brief Save -/// @param filename -void FrameRate::Save(wxString filename) { - TextFileWriter file(filename,_T("ASCII")); - file.WriteLineToFile(_T("# timecode format v2")); - for (size_t i=0;i newTimes) { - Unload(); - - loaded = true; - FrameRateType = VFR; - - // Set new VFR; - Frame = newTimes; - CalcAverage(); - last_time = newTimes.back(); - last_frame = (int)newTimes.size(); -} - -/// @brief Gets frame number at time -/// @param ms -/// @param start -/// @return -int FrameRate::PFrameAtTime(int ms,bool start) const { - if (!loaded) return -1; - - // Lines begin on the first frame whose start time is greater than or equal - // to the line's start time, and are last visible on the last frame whose - // start time is less than (note: not equal) the line's end time - - if (FrameRateType == CFR || Frame.size() == 0 || ms < 0) { - double value = double(ms) * AverageFrameRate / 1000.; - if (start) return (int)ceil(value); - else return (int)floor(value - .0001); - } - else if (FrameRateType == VFR) { - // Inside VFR range - if (ms <= Frame.back()) { - int frame = std::distance(Frame.begin(), std::lower_bound(Frame.begin(), Frame.end(), ms)); - if (!start && frame > 0) { - // In the end case, frame is the first frame in which the line - // is no longer visible, so subtract 1 - - // Don't need to worry about the equal case here as lower_bound - // finds the entry >= ms - - // The frame > 0 check isn't actually correct -- the frame - // ending at time 0 should be -1, but parts of the program - // (like PTimeAtFrame below) assume that frames are positive - --frame; - } - return frame; - } - // After VFR range - else { - if (start) return (int)(last_frame + ceil((ms-last_time) * AverageFrameRate / 1000.)); - else return (int)(last_frame + floor((ms-last_time - .0001) * AverageFrameRate / 1000.)); - } - } - return -1; -} - -/// @brief Gets time at frame -/// @param frame -/// @return -int FrameRate::PTimeAtFrame(int frame) const { - // Not loaded - if (!loaded) return -1; - - // For negative/zero times, fallback to zero - if (frame <= 0) return 0; - - // Constant frame rate - if (FrameRateType == CFR || Frame.size() == 0) { - return (int)floor(double(frame) / AverageFrameRate * 1000.0); - } - - // Variable frame rate - else if (FrameRateType == VFR) { - // Is it inside frame rate range? If so, just get the value from timecodes table - if (frame < (signed) Frame.size()) return Frame.at(frame); - - // Otherwise, calculate it - else return (int)floor(Frame.back() + double(frame-Frame.size()+1) / AverageFrameRate * 1000.0); - } - - // Unknown frame rate type - return -1; -} - -/// @brief otherwise for start frames returns the adjusted time for end frames when start=false Get correct frame at time -/// @param ms -/// @param start -/// @return -int FrameRate::GetFrameAtTime(int ms,bool start) const { - return PFrameAtTime(ms,start); -} - -/// @brief compensates and returns an end time when start=false Get correct time at frame -/// @param frame Frame number -/// @param start Adjust for start time -/// @param exact Don't do awful things to avoid rounding errors -/// @return -int FrameRate::GetTimeAtFrame(int frame,bool start,bool exact) const { - int finalTime; - - // Exact, for display - if (exact) { - finalTime = PTimeAtFrame(frame); - } - - // Adjusted, for subs sync - else { - if (start) { - finalTime = (PTimeAtFrame(frame-1) + PTimeAtFrame(frame))/2; - } - else { - //if (FrameRateType == VFR) finalTime = PTimeAtFrame(frame); - //else finalTime = (PTimeAtFrame(frame) + PTimeAtFrame(frame+1))/2; - finalTime = (PTimeAtFrame(frame) + PTimeAtFrame(frame+1))/2; - } - } - - return finalTime; -} - -/// @brief Get the current list of frames/times -/// @return -std::vector FrameRate::GetFrameTimeList() const { - return Frame; -} - -bool FrameRate::operator==(FrameRate const& rgt) { - if (FrameRateType != rgt.FrameRateType) return false; - if (FrameRateType == NONE) return true; - if (FrameRateType == CFR) return AverageFrameRate == rgt.AverageFrameRate; - return Frame == rgt.Frame; -} - -/// DOCME -FrameRate VFR_Output; - -/// DOCME -FrameRate VFR_Input; diff --git a/aegisub/src/vfr.h b/aegisub/src/vfr.h deleted file mode 100644 index 5b4a09757..000000000 --- a/aegisub/src/vfr.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Aegisub Project http://www.aegisub.org/ -// -// $Id$ - -/// @file vfr.h -/// @see vfr.cpp -/// @ingroup video_input -/// - -// The FrameRate class stores all times internally as ints in ms precision -// V1 timecodes are partially expanded to v2 up until their last override line -// V2 timecodes are kept as is and if n frames beyond the end is requested a -// time is calculated by last_time+n/average_fps - -#pragma once - - -#ifndef AGI_PRE -#include -#include - -#include -#include -#endif - -/// DOCME -enum ASS_FrameRateType { - NONE, - CFR, - VFR -}; - - -/// DOCME -/// @class FrameRate -/// @brief DOCME -/// -/// DOCME -class FrameRate { - friend class VideoContext; - -private: - - /// DOCME - double last_time; - - /// DOCME - int last_frame; - - /// DOCME - std::vector Frame; - - - /// DOCME - double AverageFrameRate; - - void AddFrame(int ms); - void Clear(); - - void CalcAverage(); - int PFrameAtTime(int ms,bool useCeil=false) const; - int PTimeAtFrame(int frame) const; - - - /// DOCME - ASS_FrameRateType FrameRateType; - - /// DOCME - bool loaded; - - /// DOCME - wxString vfrFile; - -public: - FrameRate(); - ~FrameRate(); - - void SetCFR(double fps); - void SetVFR(std::vector times); - - // Loading always unloads even on failure - void Load(wxString file); - void Save(wxString file); - void Unload(); - - int GetFrameAtTime(int ms,bool start=true) const; - int GetTimeAtFrame(int frame,bool start=true,bool exact=false) const; - - - /// @brief DOCME - /// @return - /// - double GetAverage() const { return AverageFrameRate; }; - - /// @brief DOCME - /// @return - /// - bool IsLoaded() const { return loaded; }; - - /// @brief DOCME - /// @return - /// - ASS_FrameRateType GetFrameRateType() const { return FrameRateType; }; - - /// @brief DOCME - /// - wxString GetFilename() const { return vfrFile; }; - - std::vector GetFrameTimeList() const; - - bool operator==(FrameRate const& rgt); -}; - -extern FrameRate VFR_Output; -extern FrameRate VFR_Input; diff --git a/aegisub/src/video_box.cpp b/aegisub/src/video_box.cpp index 2b5f8ca92..0cadb9850 100644 --- a/aegisub/src/video_box.cpp +++ b/aegisub/src/video_box.cpp @@ -58,7 +58,6 @@ #include "subs_grid.h" #include "toggle_bitmap.h" #include "utils.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_display.h" diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 28984df66..ddb07704c 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -34,9 +34,6 @@ /// @ingroup video /// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE @@ -63,6 +60,8 @@ #include "ass_time.h" #include "audio_display.h" #include "compat.h" +#include "keyframe.h" +#include #include "main.h" #include "mkv_wrap.h" #include "options.h" @@ -71,97 +70,64 @@ #include "subs_grid.h" #include "subtitles_provider_manager.h" #include "utils.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_display.h" #include "video_provider_manager.h" - -/////// -// IDs +/// IDs enum { - - /// DOCME VIDEO_PLAY_TIMER = 1300 }; - -/////////////// -// Event table BEGIN_EVENT_TABLE(VideoContext, wxEvtHandler) EVT_TIMER(VIDEO_PLAY_TIMER,VideoContext::OnPlayTimer) END_EVENT_TABLE() -/// DOCME -VideoContext *VideoContext::instance = NULL; - /// @brief Constructor /// VideoContext::VideoContext() : ownGlContext(false) , glContext(NULL) -, provider(NULL) -, subsProvider(NULL) -, keyFramesLoaded(false) -, overKeyFramesLoaded(false) , startFrame(-1) , endFrame(-1) , playNextFrame(-1) , nextFrame(-1) -, loaded(false) , isPlaying(false) , keepAudioSync(true) -, w(-1) -, h(-1) , frame_n(0) , length(0) -, fps(0) , arValue(1.) , arType(0) , hasSubtitles(false) , playAudioOnStep(OPT_GET("Audio/Plays When Stepping Video")) , grid(NULL) -, curLine(NULL) , audio(NULL) +, VFR_Input(videoFPS) +, VFR_Output(ovrFPS) { } -/// @brief Destructor -/// VideoContext::~VideoContext () { - Reset(); + if (audio && audio->temporary) { + delete audio->provider; + delete audio->player; + } + tempFrame.Clear(); if (ownGlContext) delete glContext; - glContext = NULL; } -/// @brief Get Instance -/// @return -/// VideoContext *VideoContext::Get() { - if (!instance) { - instance = new VideoContext; - } - return instance; + static VideoContext instance; + return &instance; } -/// @brief Clear -/// -void VideoContext::Clear() { - instance->audio = NULL; - delete instance; - instance = NULL; -} - -/// @brief Reset -/// void VideoContext::Reset() { - loaded = false; - StandardPaths::SetPathValue(_T("?video"),_T("")); + StandardPaths::SetPathValue(_T("?video"), ""); - KeyFrames.Clear(); - keyFramesLoaded = false; + keyFrames.clear(); + videoFPS = agi::vfr::Framerate(); // Remove temporary audio provider if (audio && audio->temporary) { @@ -175,133 +141,82 @@ void VideoContext::Reset() { // Remove video data frame_n = 0; length = 0; - fps = 0; - keyFramesLoaded = false; - overKeyFramesLoaded = false; isPlaying = false; nextFrame = -1; - curLine = NULL; - // Update displays UpdateDisplays(true); // Clean up video data - wxRemoveFile(tempfile); - tempfile = _T(""); - videoName = _T(""); + videoName.clear(); tempFrame.Clear(); // Remove provider - if (provider) { - delete provider; - provider = NULL; - } - delete subsProvider; - subsProvider = NULL; + provider.reset(); + subsProvider.reset(); } -/// @brief Reload video -/// -void VideoContext::Reload() { - if (IsLoaded()) { - wxString name = videoName; - int n = frame_n; - SetVideo(_T("")); - SetVideo(name); - JumpToFrame(n); - } -} - -/// @brief Sets video filename -/// @param filename -/// void VideoContext::SetVideo(const wxString &filename) { - // Unload video + Stop(); Reset(); + if (filename.empty()) return; - // Load video - if (!filename.IsEmpty()) { + try { + grid->CommitChanges(true); + + // Set GL context + GetGLContext(displayList.front())->SetCurrent(*displayList.front()); + + // Choose a provider + provider.reset(VideoProviderFactoryManager::GetProvider(filename)); + + // Get subtitles provider try { - grid->CommitChanges(true); - - // Set GL context - GetGLContext(displayList.front())->SetCurrent(*displayList.front()); - - // Choose a provider - provider = VideoProviderFactoryManager::GetProvider(filename); - loaded = provider != NULL; - - // Get subtitles provider - try { - subsProvider = SubtitlesProviderFactoryManager::GetProvider(); - } - catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider")); } - catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider")); } - - KeyFrames.Clear(); - // load keyframes if available - if (provider->AreKeyFramesLoaded()) { - KeyFrames = provider->GetKeyFrames(); - keyFramesLoaded = true; - } - else { - keyFramesLoaded = false; - } - - // Set frame rate - fps = provider->GetFPS(); - // does this provider need special vfr treatment? - if (provider->NeedsVFRHack()) { - // FIXME: - // Unfortunately, this hack does not actually work for the one - // provider that needs it (Avisynth). Go figure. - bool isVfr = provider->IsVFR(); - if (!isVfr || provider->IsNativelyByFrames()) { - VFR_Input.SetCFR(fps); - if (VFR_Output.GetFrameRateType() != VFR) VFR_Output.SetCFR(fps); - } - else { - FrameRate temp = provider->GetTrueFrameRate(); - provider->OverrideFrameTimeList(temp.GetFrameTimeList()); - } - } - - // Gather video parameters - length = provider->GetFrameCount(); - w = provider->GetWidth(); - h = provider->GetHeight(); - - // Set filename - videoName = filename; - config::mru->Add("Video", STD_STR(filename)); - wxFileName fn(filename); - StandardPaths::SetPathValue(_T("?video"),fn.GetPath()); - - // Get frame - frame_n = 0; - - // Show warning - wxString warning = provider->GetWarning().c_str(); - if (!warning.IsEmpty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK); - - hasSubtitles = false; - if (filename.Right(4).Lower() == L".mkv") { - hasSubtitles = MatroskaWrapper::HasSubtitles(filename); - } - - UpdateDisplays(true); + subsProvider.reset(SubtitlesProviderFactoryManager::GetProvider()); } - - catch (wxString &e) { - wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK); + catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider")); } + catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider")); } + + keyFrames = provider->GetKeyFrames(); + + // Set frame rate + videoFPS = provider->GetFPS(); + if (ovrFPS.IsLoaded()) { + int ovr = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION); + if (ovr == wxYES) { + ovrFPS = agi::vfr::Framerate(); + ovrTimecodeFile.clear(); + } } + + // Gather video parameters + length = provider->GetFrameCount(); + + // Set filename + videoName = filename; + config::mru->Add("Video", STD_STR(filename)); + wxFileName fn(filename); + StandardPaths::SetPathValue(_T("?video"),fn.GetPath()); + + // Get frame + frame_n = 0; + + // Show warning + wxString warning = provider->GetWarning(); + if (!warning.empty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK); + + hasSubtitles = false; + if (filename.Right(4).Lower() == L".mkv") { + hasSubtitles = MatroskaWrapper::HasSubtitles(filename); + } + + UpdateDisplays(true); + } + + catch (wxString &e) { + wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK); } } -/// @brief Add new display -/// @param display -/// @return -/// void VideoContext::AddDisplay(VideoDisplay *display) { for (std::list::iterator cur=displayList.begin();cur!=displayList.end();cur++) { if ((*cur) == display) return; @@ -309,15 +224,12 @@ void VideoContext::AddDisplay(VideoDisplay *display) { displayList.push_back(display); } -/// @brief Remove display -/// @param display -/// void VideoContext::RemoveDisplay(VideoDisplay *display) { displayList.remove(display); } void VideoContext::UpdateDisplays(bool full, bool seek) { - if (!loaded) return; + if (!IsLoaded()) return; for (std::list::iterator cur=displayList.begin();cur!=displayList.end();cur++) { VideoDisplay *display = *cur; @@ -343,9 +255,8 @@ void VideoContext::UpdateDisplays(bool full, bool seek) { } } -/// @brief Refresh subtitles void VideoContext::Refresh () { - if (subsProvider) { + if (subsProvider.get()) { AssExporter exporter(grid->ass); exporter.AddAutoFilters(); try { @@ -358,12 +269,8 @@ void VideoContext::Refresh () { UpdateDisplays(false); } -/// @brief Jumps to a frame and update display -/// @param n -/// @return -/// void VideoContext::JumpToFrame(int n) { - if (!loaded) return; + if (!IsLoaded()) return; // Prevent intervention during playback if (isPlaying && n != playNextFrame) return; @@ -372,30 +279,14 @@ void VideoContext::JumpToFrame(int n) { UpdateDisplays(false, true); - // Update grid static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame"); if (!isPlaying && highlight->GetBool()) grid->Refresh(false); } - - -/// @brief Jumps to a specific time -/// @param ms -/// @param exact -/// -void VideoContext::JumpToTime(int ms,bool exact) { - int frame; - if (exact) frame = VFR_Output.PFrameAtTime(ms); - else frame = VFR_Output.GetFrameAtTime(ms); - JumpToFrame(frame); +void VideoContext::JumpToTime(int ms, agi::vfr::Time end) { + JumpToFrame(FrameAtTime(ms, end)); } - - -/// @brief Get GL context -/// @param canvas -/// @return -/// wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) { if (!glContext) { glContext = new wxGLContext(canvas); @@ -404,25 +295,17 @@ wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) { return glContext; } - - -/// @brief Requests a new frame -/// @param n -/// @param raw -/// @return -/// AegiVideoFrame VideoContext::GetFrame(int n,bool raw) { // Current frame if -1 if (n == -1) n = frame_n; - // Get frame AegiVideoFrame frame = provider->GetFrame(n); // Raster subtitles if available/necessary - if (!raw && subsProvider) { + if (!raw && subsProvider.get()) { tempFrame.CopyFrom(frame); try { - subsProvider->DrawSubtitles(tempFrame,VFR_Input.GetTimeAtFrame(n,true,true)/1000.0); + subsProvider->DrawSubtitles(tempFrame,videoFPS.TimeAtFrame(n)/1000.0); } catch (...) { wxLogError(L"Subtitle rendering for the current frame failed.\n"); @@ -434,9 +317,13 @@ AegiVideoFrame VideoContext::GetFrame(int n,bool raw) { else return frame; } -/// @brief Save snapshot -/// @param raw -/// +int VideoContext::GetWidth() const { + return provider->GetWidth(); +} +int VideoContext::GetHeight() const { + return provider->GetHeight(); +} + void VideoContext::SaveSnapshot(bool raw) { // Get folder static agi::OptionValue* ssPath = OPT_GET("Path/Screenshot"); @@ -452,7 +339,7 @@ void VideoContext::SaveSnapshot(bool raw) { } // Find out where the ?specifier points to basepath = StandardPaths::DecodePath(option); - // If whereever that is isn't defined, we can't save there + // If where ever that is isn't defined, we can't save there if ((basepath == _T("\\")) || (basepath == _T("/"))) { // So save to the current user's home dir instead basepath = wxGetHomeDir(); @@ -472,21 +359,13 @@ void VideoContext::SaveSnapshot(bool raw) { if (!tryPath.FileExists()) break; } - // Save GetFrame(frame_n,raw).GetImage().SaveFile(path,wxBITMAP_TYPE_PNG); } -/// @brief Get dimensions of script -/// @param sw -/// @param sh -/// void VideoContext::GetScriptSize(int &sw,int &sh) { grid->ass->GetResolution(sw,sh); } -/// @brief Play the next frame, possibly with audio -/// @return -/// void VideoContext::PlayNextFrame() { if (isPlaying) return; @@ -495,12 +374,9 @@ void VideoContext::PlayNextFrame() { JumpToFrame(frame_n + 1); // Start playing audio if (playAudioOnStep->GetBool()) - audio->Play(VFR_Output.GetTimeAtFrame(thisFrame),VFR_Output.GetTimeAtFrame(thisFrame + 1)); + audio->Play(TimeAtFrame(thisFrame),TimeAtFrame(thisFrame + 1)); } -/// @brief Play the previous frame, possibly with audio -/// @return -/// void VideoContext::PlayPrevFrame() { if (isPlaying) return; @@ -509,14 +385,10 @@ void VideoContext::PlayPrevFrame() { JumpToFrame(frame_n -1); // Start playing audio if (playAudioOnStep->GetBool()) - audio->Play(VFR_Output.GetTimeAtFrame(thisFrame - 1),VFR_Output.GetTimeAtFrame(thisFrame)); + audio->Play(TimeAtFrame(thisFrame - 1),TimeAtFrame(thisFrame)); } -/// @brief Play -/// @return -/// void VideoContext::Play() { - // Stop if already playing if (isPlaying) { Stop(); return; @@ -527,7 +399,7 @@ void VideoContext::Play() { endFrame = -1; // Start playing audio - audio->Play(VFR_Output.GetTimeAtFrame(startFrame),-1); + audio->Play(TimeAtFrame(startFrame),-1); //audio->Play will override this if we put it before, so put it after. isPlaying = true; @@ -538,14 +410,7 @@ void VideoContext::Play() { playback.Start(10); } - - - -/// @brief Play line -/// @return -/// void VideoContext::PlayLine() { - // Get line AssDialogue *curline = grid->GetActiveLine(); if (!curline) return; @@ -554,8 +419,8 @@ void VideoContext::PlayLine() { // Set variables isPlaying = true; - startFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true); - endFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false); + startFrame = FrameAtTime(curline->Start.GetMS(),agi::vfr::START); + endFrame = FrameAtTime(curline->End.GetMS(),agi::vfr::END); // Jump to start playNextFrame = startFrame; @@ -569,8 +434,6 @@ void VideoContext::PlayLine() { playback.Start(10); } -/// @brief Stop -/// void VideoContext::Stop() { if (isPlaying) { playback.Stop(); @@ -579,10 +442,6 @@ void VideoContext::Stop() { } } -/// @brief Play timer -/// @param event -/// @return -/// void VideoContext::OnPlayTimer(wxTimerEvent &event) { // Lock wxMutexError res = playMutex.TryLock(); @@ -594,12 +453,12 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) { int dif = playTime.Time(); // Find next frame - int startMs = VFR_Output.GetTimeAtFrame(startFrame); + int startMs = TimeAtFrame(startFrame); int nextFrame = frame_n; int i=0; for (i=0;i<10;i++) { if (nextFrame >= length) break; - if (dif < VFR_Output.GetTimeAtFrame(nextFrame) - startMs) { + if (dif < TimeAtFrame(nextFrame) - startMs) { break; } nextFrame++; @@ -615,7 +474,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) { if (nextFrame == frame_n) return; // Next frame is before or over 2 frames ahead, so force audio resync - if (audio->player && keepAudioSync && (nextFrame < frame_n || nextFrame > frame_n + 2)) audio->player->SetCurrentPosition(audio->GetSampleAtMS(VFR_Output.GetTimeAtFrame(nextFrame))); + if (audio->player && keepAudioSync && (nextFrame < frame_n || nextFrame > frame_n + 2)) audio->player->SetCurrentPosition(audio->GetSampleAtMS(TimeAtFrame(nextFrame))); // Jump to next frame playNextFrame = nextFrame; @@ -624,7 +483,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) { // Sync audio if (keepAudioSync && nextFrame % 10 == 0 && audio && audio->provider && audio->player) { - int64_t audPos = audio->GetSampleAtMS(VFR_Output.GetTimeAtFrame(nextFrame)); + int64_t audPos = audio->GetSampleAtMS(TimeAtFrame(nextFrame)); int64_t curPos = audio->player->GetCurrentPosition(); int delta = int(audPos-curPos); if (delta < 0) delta = -delta; @@ -633,67 +492,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) { } } -/// @brief Get name of temp work file -/// @return -/// -wxString VideoContext::GetTempWorkFile () { - if (tempfile.IsEmpty()) { - tempfile = wxFileName::CreateTempFileName(_T("aegisub")); - wxRemoveFile(tempfile); - tempfile += _T(".ass"); - } - return tempfile; -} - -/// @brief Get keyframes -/// @return -/// -wxArrayInt VideoContext::GetKeyFrames() { - if (OverKeyFramesLoaded()) return overKeyFrames; - return KeyFrames; -} - -/// @brief Set keyframes -/// @param frames -/// -void VideoContext::SetKeyFrames(wxArrayInt frames) { - KeyFrames = frames; -} - -/// @brief Set keyframe override -/// @param frames -/// -void VideoContext::SetOverKeyFrames(wxArrayInt frames) { - overKeyFrames = frames; - overKeyFramesLoaded = true; -} - -/// @brief Close keyframes -/// -void VideoContext::CloseOverKeyFrames() { - overKeyFrames.Clear(); - overKeyFramesLoaded = false; -} - -/// @brief Check if override keyframes are loaded -/// @return -/// -bool VideoContext::OverKeyFramesLoaded() { - return overKeyFramesLoaded; -} - -/// @brief Check if keyframes are loaded -/// @return -/// -bool VideoContext::KeyFramesLoaded() { - return overKeyFramesLoaded || keyFramesLoaded; -} - -/// @brief Calculate aspect ratio -/// @param type -/// @return -/// -double VideoContext::GetARFromType(int type) { +double VideoContext::GetARFromType(int type) const { if (type == 0) return (double)VideoContext::Get()->GetWidth()/(double)VideoContext::Get()->GetHeight(); if (type == 1) return 4.0/3.0; if (type == 2) return 16.0/9.0; @@ -701,18 +500,77 @@ double VideoContext::GetARFromType(int type) { return 1.0; //error } -/// @brief Sets aspect ratio -/// @param _type -/// @param value -/// -void VideoContext::SetAspectRatio(int _type, double value) { - // Get value - if (_type != 4) value = GetARFromType(_type); +void VideoContext::SetAspectRatio(int type, double value) { + if (type != 4) value = GetARFromType(type); if (value < 0.5) value = 0.5; if (value > 5.0) value = 5.0; - // Set - arType = _type; + arType = type; arValue = value; UpdateDisplays(true); } + +void VideoContext::LoadKeyframes(wxString filename) { + if (filename == keyFramesFilename || filename.empty()) return; + keyFrames = KeyFrameFile::Load(filename); + keyFramesFilename = filename; + Refresh(); +} + +void VideoContext::SaveKeyframes(wxString filename) { + KeyFrameFile::Save(filename, GetKeyFrames()); +} + +void VideoContext::CloseKeyframes() { + keyFramesFilename.clear(); + if (provider.get()) { + keyFrames = provider->GetKeyFrames(); + } + else { + keyFrames.clear(); + } + Refresh(); +} + +void VideoContext::LoadTimecodes(wxString filename) { + if (filename == ovrTimecodeFile || filename.empty()) return; + try { + ovrFPS = agi::vfr::Framerate(STD_STR(filename)); + ovrTimecodeFile = filename; + config::mru->Add("Timecodes", STD_STR(filename)); + Refresh(); + } + catch (const agi::acs::AcsError&) { + wxLogError(L"Could not open file " + filename); + } + catch (const agi::vfr::Error& e) { + wxLogError(L"Timecode file parse error: %s", e.GetMessage().c_str()); + } +} +void VideoContext::SaveTimecodes(wxString filename) { + try { + ovrFPS.Save(STD_STR(filename), IsLoaded() ? length : -1); + config::mru->Add("Timecodes", STD_STR(filename)); + } + catch(const agi::acs::AcsError&) { + wxLogError(L"Could not write to " + filename); + } +} +void VideoContext::CloseTimecodes() { + ovrFPS = agi::vfr::Framerate(); + ovrTimecodeFile.clear(); + Refresh(); +} + +int VideoContext::TimeAtFrame(int frame, agi::vfr::Time type) const { + if (ovrFPS.IsLoaded()) { + return ovrFPS.TimeAtFrame(frame, type); + } + return videoFPS.TimeAtFrame(frame, type); +} +int VideoContext::FrameAtTime(int time, agi::vfr::Time type) const { + if (ovrFPS.IsLoaded()) { + return ovrFPS.FrameAtTime(time, type); + } + return videoFPS.FrameAtTime(time, type); +} diff --git a/aegisub/src/video_context.h b/aegisub/src/video_context.h index 956cfe038..f715bec00 100644 --- a/aegisub/src/video_context.h +++ b/aegisub/src/video_context.h @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -56,12 +57,14 @@ #include #endif +#include #include "video_frame.h" class SubtitlesGrid; class AudioProvider; class AudioDisplay; class AssDialogue; +class KeyFrameFile; class SubtitlesProvider; class VideoProvider; class VideoDisplay; @@ -77,11 +80,9 @@ namespace agi { /// DOCME class VideoContext : public wxEvtHandler { friend class AudioProvider; + friend class KeyFrameFile; private: - /// DOCME - static VideoContext *instance; - /// DOCME std::list displayList; @@ -94,27 +95,14 @@ private: /// DOCME AegiVideoFrame tempFrame; + /// DOCME + std::auto_ptr provider; /// DOCME - wxString tempfile; + std::auto_ptr subsProvider; /// DOCME - VideoProvider *provider; - - /// DOCME - SubtitlesProvider *subsProvider; - - /// DOCME - bool keyFramesLoaded; - - /// DOCME - bool overKeyFramesLoaded; - - /// DOCME - wxArrayInt KeyFrames; - - /// DOCME - wxArrayInt overKeyFrames; + std::vector keyFrames; /// DOCME wxString keyFramesFilename; @@ -140,29 +128,18 @@ private: /// DOCME int nextFrame; - /// DOCME - bool loaded; - /// DOCME bool isPlaying; /// DOCME bool keepAudioSync; - /// DOCME - - /// DOCME - int w,h; - /// DOCME int frame_n; /// DOCME int length; - /// DOCME - double fps; - /// DOCME double arValue; @@ -171,24 +148,28 @@ private: bool hasSubtitles; + wxString ovrTimecodeFile; + agi::OptionValue* playAudioOnStep; void OnPlayTimer(wxTimerEvent &event); + agi::vfr::Framerate videoFPS; + agi::vfr::Framerate ovrFPS; + public: /// DOCME SubtitlesGrid *grid; - /// DOCME + /// File name of currently open video, if any wxString videoName; - - /// DOCME - AssDialogue *curLine; - /// DOCME AudioDisplay *audio; + const agi::vfr::Framerate &VFR_Input; + const agi::vfr::Framerate &VFR_Output; + VideoContext(); ~VideoContext(); @@ -196,110 +177,114 @@ public: void RemoveDisplay(VideoDisplay *display); - /// @brief DOCME - /// @return - /// - VideoProvider *GetProvider() { return provider; } + /// @brief Get the video provider used for the currently open video + VideoProvider *GetProvider() const { return provider.get(); } AegiVideoFrame GetFrame(int n,bool raw=false); + /// @brief Save the currently displayed frame as an image + /// @param raw Should the frame have subtitles? void SaveSnapshot(bool raw); wxGLContext *GetGLContext(wxGLCanvas *canvas); - /// @brief DOCME - /// @return - bool IsLoaded() { return loaded; } + /// @brief Is there a video loaded? + bool IsLoaded() const { return !!provider.get(); } - /// @brief DOCME - /// @return - bool IsPlaying() { return isPlaying; } + /// @brief Is the video currently playing? + bool IsPlaying() const { return isPlaying; } /// @brief Does the video file loaded have muxed subtitles that we can load? - bool HasSubtitles() {return hasSubtitles; } + bool HasSubtitles() const { return hasSubtitles; } /// @brief DOCME /// @param sync /// @return void EnableAudioSync(bool sync = true) { keepAudioSync = sync; } + /// @brief Get the width of the currently open video + int GetWidth() const; - /// @brief DOCME - /// @return - int GetWidth() { return w; } + /// @brief Get the height of the currently open video + int GetHeight() const; - /// @brief DOCME - /// @return - int GetHeight() { return h; } + /// @brief Get the length in frames of the currently open video + int GetLength() const { return length; } - /// @brief DOCME - /// @return - int GetLength() { return length; } + /// @brief Get the current frame number + int GetFrameN() const { return frame_n; } - /// @brief DOCME - /// @return - int GetFrameN() { return frame_n; } - - /// @brief DOCME - /// @return - double GetFPS() { return fps; } - - /// @brief DOCME - /// @param _fps - /// @return - void SetFPS(double fps) { this->fps = fps; } - - double GetARFromType(int type); + double GetARFromType(int type) const; void SetAspectRatio(int type,double value=1.0); /// @brief DOCME /// @return - int GetAspectRatioType() { return arType; } + int GetAspectRatioType() const { return arType; } /// @brief DOCME /// @return - double GetAspectRatioValue() { return arValue; } + double GetAspectRatioValue() const { return arValue; } + /// @brief Open a new video + /// @param filename Video to open, or empty to close the current video void SetVideo(const wxString &filename); + /// @brief Close the video, keyframes and timecodes void Reset(); - void Reload(); + /// @brief Jump to the beginning of a frame + /// @param n Frame number to jump to void JumpToFrame(int n); - void JumpToTime(int ms,bool exact=false); + /// @brief Jump to a time + /// @param ms Time to jump to in milliseconds + /// @param end Type of time + void JumpToTime(int ms, agi::vfr::Time end = agi::vfr::START); + /// @brief Refresh the subtitle provider void Refresh(); + /// @brief Update the video display /// @param full Recalculate size and slider lengths /// @param seek Update is just a seek and file has not changed void UpdateDisplays(bool full, bool seek = false); + /// @brief Get the height and width of the current script + /// @param[out] w Width + /// @param[out] h Height + /// + /// This probably shouldn't be in VideoContext void GetScriptSize(int &w,int &h); - wxString GetTempWorkFile (); + /// Starting playing the video void Play(); + /// Play the next frame then stop void PlayNextFrame(); + /// Play the previous frame then stop void PlayPrevFrame(); + /// Seek to the beginning of the current line, then play to the end of it void PlayLine(); + /// Stop playing void Stop(); - wxArrayInt GetKeyFrames(); - void SetKeyFrames(wxArrayInt frames); - void SetOverKeyFrames(wxArrayInt frames); - void CloseOverKeyFrames(); - bool OverKeyFramesLoaded(); - bool KeyFramesLoaded(); + const std::vector& GetKeyFrames() const { return keyFrames; }; + wxString GetKeyFramesName() const { return keyFramesFilename; } + void LoadKeyframes(wxString filename); + void SaveKeyframes(wxString filename); + void CloseKeyframes(); + bool OverKeyFramesLoaded() const { return !keyFramesFilename.empty(); } + bool KeyFramesLoaded() const { return !keyFrames.empty(); } - /// @brief DOCME - /// @return - /// - wxString GetKeyFramesName() { return keyFramesFilename; } + wxString GetTimecodesName() const { return ovrTimecodeFile; } + void LoadTimecodes(wxString filename); + void SaveTimecodes(wxString filename); + void CloseTimecodes(); + bool OverTimecodesLoaded() const { return ovrFPS.IsLoaded(); } + bool TimecodesLoaded() const { return videoFPS.IsLoaded() || ovrFPS.IsLoaded(); }; - /// @brief DOCME - /// @param name - /// - void SetKeyFramesName(wxString name) { keyFramesFilename = name; } + const agi::vfr::Framerate& FPS() const { return ovrFPS.IsLoaded() ? ovrFPS : videoFPS; } + + int TimeAtFrame(int frame, agi::vfr::Time type = agi::vfr::EXACT) const; + int FrameAtTime(int time, agi::vfr::Time type = agi::vfr::EXACT) const; static VideoContext *Get(); - static void Clear(); DECLARE_EVENT_TABLE() }; diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp index 5edf5746d..e30a80c31 100644 --- a/aegisub/src/video_display.cpp +++ b/aegisub/src/video_display.cpp @@ -60,8 +60,8 @@ #include "hotkeys.h" #include "options.h" #include "main.h" +#include "subs_grid.h" #include "video_out_gl.h" -#include "vfr.h" #include "video_box.h" #include "video_context.h" #include "video_slider.h" @@ -166,7 +166,7 @@ void VideoDisplay::SetFrame(int frameNumber) { // Get time for frame { - int time = VFR_Output.GetTimeAtFrame(frameNumber, true, true); + int time = context->TimeAtFrame(frameNumber, agi::vfr::EXACT); int h = time / 3600000; int m = time % 3600000 / 60000; int s = time % 60000 / 1000; @@ -174,7 +174,7 @@ void VideoDisplay::SetFrame(int frameNumber) { // Set the text box for frame number and time PositionDisplay->SetValue(wxString::Format(L"%01i:%02i:%02i.%03i - %i", h, m, s, ms, frameNumber)); - if (context->GetKeyFrames().Index(frameNumber) != wxNOT_FOUND) { + if (std::binary_search(context->GetKeyFrames().begin(), context->GetKeyFrames().end(), frameNumber)) { // Set the background color to indicate this is a keyframe PositionDisplay->SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColour())); PositionDisplay->SetForegroundColour(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Selection")->GetColour())); @@ -189,7 +189,7 @@ void VideoDisplay::SetFrame(int frameNumber) { int startOff = 0; int endOff = 0; - if (AssDialogue *curLine = context->curLine) { + if (AssDialogue *curLine = context->grid->GetActiveLine()) { startOff = time - curLine->Start.GetMS(); endOff = time - curLine->End.GetMS(); } diff --git a/aegisub/src/video_provider_avs.cpp b/aegisub/src/video_provider_avs.cpp index e385efeda..c1e983bee 100644 --- a/aegisub/src/video_provider_avs.cpp +++ b/aegisub/src/video_provider_avs.cpp @@ -50,7 +50,6 @@ #include "mkv_wrap.h" #include "options.h" #include "standard_paths.h" -#include "vfr.h" #include "vfw_wrap.h" #include "video_context.h" #include "video_provider_avs.h" @@ -63,13 +62,9 @@ AvisynthVideoProvider::AvisynthVideoProvider(wxString _filename) { AVSTRACE(wxString::Format(_T("AvisynthVideoProvider: Creating new AvisynthVideoProvider: \"%s\", \"%s\""), _filename, _subfilename)); bool mpeg2dec3_priority = true; RGB32Video = NULL; - fps = 0; num_frames = 0; last_fnum = -1; - byFrame = false; - KeyFrames.Clear(); - keyFramesLoaded = false; - isVfr = false; + KeyFrames.clear(); AVSTRACE(_T("AvisynthVideoProvider: Opening video")); RGB32Video = OpenVideo(_filename,mpeg2dec3_priority); @@ -92,12 +87,6 @@ AvisynthVideoProvider::~AvisynthVideoProvider() { AVSTRACE(_T("AvisynthVideoProvider: AvisynthVideoProvider destroyed")); } - - -////////////////////////////////////// VIDEO PROVIDER ////////////////////////////////////// - - - /// @brief Actually open the video into Avisynth /// @param _filename /// @param mpeg2dec3_priority @@ -109,7 +98,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Got AVS mutex")); AVSValue script; - byFrame = false; usedDirectShow = false; decoderName = _("Unknown"); @@ -138,7 +126,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori AVSValue args[2] = { videoFilename, false }; script = env->Invoke("AviSource", AVSValue(args,2), argnames); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio")); - byFrame = true; decoderName = _T("AviSource"); } @@ -155,10 +142,10 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename); decoderName = _T("Mpeg2Dec3_Mpeg2Source"); - //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this + //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this if (env->FunctionExists("SetPlanarLegacyAlignment")) { AVSValue args[2] = { script, true }; - script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2)); + script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2)); } } @@ -168,8 +155,8 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori script = env->Invoke("Mpeg2Source", videoFilename); decoderName = _T("DGDecode_Mpeg2Source"); - //note that DGDecode will also have issues like if the version is too ancient but no sane person - //would use that anyway + //note that DGDecode will also have issues like if the version is too ancient but no sane person + //would use that anyway } else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) { @@ -177,9 +164,9 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori script = env->Invoke("Mpeg2Source", videoFilename); decoderName = _T("Mpeg2Source"); - //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this - if (env->FunctionExists("SetPlanarLegacyAlignment")) - script = env->Invoke("SetPlanarLegacyAlignment", script); + //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this + if (env->FunctionExists("SetPlanarLegacyAlignment")) + script = env->Invoke("SetPlanarLegacyAlignment", script); } // Some other format, such as mkv, mp4, ogm... try both flavors of DirectShowSource @@ -253,30 +240,16 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori } // Read keyframes and timecodes from MKV file - isVfr = false; - FrameRate temp; bool mkvOpen = MatroskaWrapper::wrapper.IsOpen(); - KeyFrames.Clear(); + KeyFrames.clear(); if (extension == _T(".mkv") || mkvOpen) { // Parse mkv if (!mkvOpen) MatroskaWrapper::wrapper.Open(_filename); // Get keyframes KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames(); - keyFramesLoaded = true; - - // Ask to override timecodes - int override = wxYES; - if (VFR_Output.IsLoaded()) override = wxMessageBox(_("You already have timecodes loaded. Replace them with the timecodes from the Matroska file?"),_("Replace timecodes?"),wxYES_NO | wxICON_QUESTION); - if (override == wxYES) { - MatroskaWrapper::wrapper.SetToTimecodes(temp); - isVfr = temp.GetFrameRateType() == VFR; - if (isVfr) { - MatroskaWrapper::wrapper.SetToTimecodes(VFR_Input); - MatroskaWrapper::wrapper.SetToTimecodes(VFR_Output); - trueFrameRate = temp; - } - } + + MatroskaWrapper::wrapper.SetToTimecodes(vfr_fps); // Close mkv MatroskaWrapper::wrapper.Close(); @@ -284,16 +257,14 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori // check if we have windows, if so we can load keyframes from AVI files using VFW #ifdef __WINDOWS__ else if (extension == _T(".avi")) { - keyFramesLoaded = false; - KeyFrames.Clear(); + KeyFrames.clear(); KeyFrames = VFWWrapper::GetKeyFrames(_filename); - keyFramesLoaded = true; } #endif /* __WINDOWS__ */ // Check if the file is all keyframes bool isAllKeyFrames = true; - for (unsigned int i=1; iInvoke("ConvertToRGB32", script); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Converted to RGB32")); @@ -323,17 +295,10 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori /// @param _n /// @return /// -const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n) { - // Transform n if overriden - int n = _n; - if (frameTime.Count()) { - if (n < 0) n = 0; - if (n >= (signed) frameTime.Count()) n = frameTime.Count()-1; - int time = frameTime[n]; - double curFps = (double)vi.fps_numerator/(double)vi.fps_denominator; - n = time * curFps / 1000.0; +const AegiVideoFrame AvisynthVideoProvider::GetFrame(int n) { + if (vfr_fps.IsLoaded()) { + n = real_fps.FrameAtTime(vfr_fps.TimeAtFrame(n)); } - // Get avs frame AVSTRACE(_T("AvisynthVideoProvider::GetFrame")); wxMutexLocker lock(AviSynthMutex); @@ -362,24 +327,11 @@ const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n) { return final; } - -/// @brief Override frame times -/// @param list -/// -void AvisynthVideoProvider::OverrideFrameTimeList(wxArrayInt list) { - frameTime = list; - num_frames = frameTime.Count(); -} - - - /// @brief Get warning /// -wxString AvisynthVideoProvider::GetWarning() { +wxString AvisynthVideoProvider::GetWarning() const { if (usedDirectShow) return L"Warning! The file is being opened using Avisynth's DirectShowSource, which has unreliable seeking. Frame numbers might not match the real number. PROCEED AT YOUR OWN RISK!"; else return L""; } #endif - - diff --git a/aegisub/src/video_provider_avs.h b/aegisub/src/video_provider_avs.h index 556b407e9..389462475 100644 --- a/aegisub/src/video_provider_avs.h +++ b/aegisub/src/video_provider_avs.h @@ -34,22 +34,16 @@ /// @ingroup video_input /// - -/////////// -// Headers #ifdef WITH_AVISYNTH #include "avisynth_wrap.h" #include "include/aegisub/video_provider.h" - /// DOCME /// @class AvisynthVideoProvider /// @brief DOCME /// /// DOCME class AvisynthVideoProvider: public VideoProvider, AviSynthWrapper { -private: - /// DOCME VideoInfo vi; @@ -75,27 +69,11 @@ private: /// DOCME - double fps; + agi::vfr::Framerate real_fps; + agi::vfr::Framerate vfr_fps; /// DOCME - wxArrayInt frameTime; - - /// DOCME - bool byFrame; - - - /// DOCME - wxArrayInt KeyFrames; - - /// DOCME - bool keyFramesLoaded; - - /// DOCME - bool isVfr; - - /// DOCME - FrameRate trueFrameRate; - + std::vector KeyFrames; /// DOCME PClip RGB32Video; @@ -108,72 +86,16 @@ public: const AegiVideoFrame GetFrame(int n); - /// @brief // properties - /// @return - /// - int GetPosition() { return last_fnum; }; - - /// @brief DOCME - /// @return - /// - int GetFrameCount() { return num_frames? num_frames: vi.num_frames; }; - - /// @brief DOCME - /// @return - /// - double GetFPS() { return (double)vi.fps_numerator/(double)vi.fps_denominator; }; - - /// @brief DOCME - /// @return - /// - int GetWidth() { return vi.width; }; - - /// @brief DOCME - /// @return - /// - int GetHeight() { return vi.height; }; - - /// @brief DOCME - /// @return - /// - bool AreKeyFramesLoaded() { return keyFramesLoaded; }; - - /// @brief DOCME - /// @return - /// - wxArrayInt GetKeyFrames() { return KeyFrames; }; - - /// @brief DOCME - /// @return - /// - bool IsVFR() { return isVfr; }; - - /// @brief DOCME - /// @return - /// - FrameRate GetTrueFrameRate() { return isVfr? trueFrameRate: FrameRate(); }; - - void OverrideFrameTimeList(wxArrayInt list); - - /// @brief DOCME - /// @return - /// - bool IsNativelyByFrames() { return byFrame; } - - /// @brief DOCME - /// @return - /// - bool NeedsVFRHack() { return true; } - wxString GetWarning(); - - /// @brief DOCME - /// @return - /// - wxString GetDecoderName() { return wxString(L"Avisynth/") + decoderName; } + int GetPosition() const { return last_fnum; }; + int GetFrameCount() const { return num_frames? num_frames: vi.num_frames; }; + agi::vfr::Framerate GetFPS() const { return vfr_fps.IsLoaded() ? vfr_fps : real_fps; }; + int GetWidth() const { return vi.width; }; + int GetHeight() const { return vi.height; }; + std::vector GetKeyFrames() const { return KeyFrames; }; + wxString GetWarning() const; + wxString GetDecoderName() const { return wxString(L"Avisynth/") + decoderName; } }; - - /// DOCME /// @class AvisynthVideoProviderFactory /// @brief DOCME @@ -188,7 +110,4 @@ public: VideoProvider *CreateProvider(wxString video) { return new AvisynthVideoProvider(video); } }; - #endif - - diff --git a/aegisub/src/video_provider_cache.cpp b/aegisub/src/video_provider_cache.cpp index c0f94662d..85692c1b2 100644 --- a/aegisub/src/video_provider_cache.cpp +++ b/aegisub/src/video_provider_cache.cpp @@ -34,39 +34,43 @@ /// @ingroup video_input /// - -/////////// -// Headers #include "config.h" #include "main.h" #include "options.h" #include "video_provider_cache.h" +/// DOCME +/// @class CachedFrame +/// @brief DOCME +/// +/// DOCME +struct CachedFrame { + /// DOCME + AegiVideoFrame frame; + + /// DOCME + int n; +}; /// @brief Constructor /// @param parent /// -VideoProviderCache::VideoProviderCache(VideoProvider *parent) { - master = parent; - cacheMax = 0; - if (parent->WantsCaching()) - cacheMax = OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20; // convert MB to bytes - else - cacheMax = 0; +VideoProviderCache::VideoProviderCache(VideoProvider *parent) +: master(parent) +, cacheMax(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes +{ } - - /// @brief Destructor /// VideoProviderCache::~VideoProviderCache() { - delete master; - ClearCache(); + while (cache.size()) { + cache.front().frame.Clear(); + cache.pop_front(); + } } - - /// @brief Get frame /// @param n /// @return @@ -88,21 +92,14 @@ const AegiVideoFrame VideoProviderCache::GetFrame(int n) { const AegiVideoFrame *srcFrame = &frame; // Cache frame - pos = n; Cache(n,*srcFrame); return *srcFrame; } - /// @brief Add to cache /// @param n /// @param frame -/// @return -/// void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) { - // Cache enabled? - if (cacheMax == 0) return; - // Cache full, use frame at front if (GetCurCacheSize() >= cacheMax) { cache.push_back(cache.front()); @@ -119,17 +116,6 @@ void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) { cache.back().frame.CopyFrom(frame); } - - -/// @brief Clear cache -/// -void VideoProviderCache::ClearCache() { - while (cache.size()) { - cache.front().frame.Clear(); - cache.pop_front(); - } -} - /// @brief Get the current size of the cache /// @return Returns the size in bytes unsigned VideoProviderCache::GetCurCacheSize() { @@ -138,103 +124,3 @@ unsigned VideoProviderCache::GetCurCacheSize() { sz += i->frame.memSize; return sz; } - - -/// @brief Wrapper methods -/// @return -/// -int VideoProviderCache::GetPosition() { - return pos; -} - -/// @brief DOCME -/// @return -/// -int VideoProviderCache::GetFrameCount() { - return master->GetFrameCount(); -} - -/// @brief DOCME -/// @return -/// -int VideoProviderCache::GetWidth() { - return master->GetWidth(); -} - -/// @brief DOCME -/// @return -/// -int VideoProviderCache::GetHeight() { - return master->GetHeight(); -} - -/// @brief DOCME -/// @return -/// -double VideoProviderCache::GetFPS() { - return master->GetFPS(); -} - -/// @brief DOCME -/// @return -/// -bool VideoProviderCache::IsVFR() { - return master->IsVFR(); -} - -/// @brief DOCME -/// @return -/// -bool VideoProviderCache::AreKeyFramesLoaded() { - return master->AreKeyFramesLoaded(); -} - -/// @brief DOCME -/// @return -/// -wxArrayInt VideoProviderCache::GetKeyFrames() { - return master->GetKeyFrames(); -} - -/// @brief DOCME -/// @return -/// -FrameRate VideoProviderCache::GetTrueFrameRate() { - return master->GetTrueFrameRate(); -} - -/// @brief DOCME -/// @param list -/// -void VideoProviderCache::OverrideFrameTimeList(std::vector list) { - master->OverrideFrameTimeList(list); -} - -/// @brief DOCME -/// @return -/// -bool VideoProviderCache::IsNativelyByFrames() { - return master->IsNativelyByFrames(); -} - -/// @brief DOCME -/// @return -/// -bool VideoProviderCache::NeedsVFRHack() { - return master->NeedsVFRHack(); -} - -/// @brief DOCME -/// @return -/// -wxString VideoProviderCache::GetWarning() { - return master->GetWarning(); -} - -/// @brief DOCME -/// -wxString VideoProviderCache::GetDecoderName() { - return master->GetDecoderName(); -} - - diff --git a/aegisub/src/video_provider_cache.h b/aegisub/src/video_provider_cache.h index c73faf307..4bd5914c7 100644 --- a/aegisub/src/video_provider_cache.h +++ b/aegisub/src/video_provider_cache.h @@ -34,34 +34,14 @@ /// @ingroup video_input /// - - - -////////// -// Headers #ifndef AGI_PRE #include +#include #endif #include "include/aegisub/video_provider.h" -#include "vfr.h" - - -/// DOCME -/// @class CachedFrame -/// @brief DOCME -/// -/// DOCME -class CachedFrame { -public: - - /// DOCME - AegiVideoFrame frame; - - /// DOCME - int n; -}; +struct CachedFrame; /// DOCME /// @class VideoProviderCache @@ -69,10 +49,8 @@ public: /// /// DOCME class VideoProviderCache : public VideoProvider { -private: - /// DOCME - VideoProvider *master; + std::auto_ptr master; /// DOCME unsigned int cacheMax; @@ -80,16 +58,11 @@ private: /// DOCME std::list cache; - /// DOCME - int pos; - void Cache(int n,const AegiVideoFrame frame); AegiVideoFrame GetCachedFrame(int n); -protected: // Cache functions unsigned GetCurCacheSize(); - void ClearCache(); public: // Base methods @@ -98,20 +71,14 @@ public: virtual ~VideoProviderCache(); // Override the following methods: - virtual int GetPosition(); // Get the number of the last frame loaded - virtual int GetFrameCount(); // Get total number of frames - virtual int GetWidth(); // Returns the video width in pixels - virtual int GetHeight(); // Returns the video height in pixels - virtual double GetFPS(); // Get framerate in frames per second - virtual bool AreKeyFramesLoaded(); - virtual bool IsVFR(); - virtual wxArrayInt GetKeyFrames(); - virtual FrameRate GetTrueFrameRate(); - virtual void OverrideFrameTimeList(std::vector list); // Override the list with the provided one, for VFR handling - virtual bool IsNativelyByFrames(); - virtual bool NeedsVFRHack(); - virtual wxString GetWarning(); - virtual wxString GetDecoderName(); + virtual int GetPosition() const { return master->GetPosition(); } + virtual int GetFrameCount() const { return master->GetFrameCount(); } + virtual int GetWidth() const { return master->GetWidth(); } + virtual int GetHeight() const { return master->GetHeight(); } + virtual agi::vfr::Framerate GetFPS() const { return master->GetFPS(); } + virtual std::vector GetKeyFrames() const { return master->GetKeyFrames(); } + virtual wxString GetWarning() const { return master->GetWarning(); } + virtual wxString GetDecoderName() const { return master->GetDecoderName(); } + + }; - - diff --git a/aegisub/src/video_provider_dummy.cpp b/aegisub/src/video_provider_dummy.cpp index 87ebca71b..883784867 100644 --- a/aegisub/src/video_provider_dummy.cpp +++ b/aegisub/src/video_provider_dummy.cpp @@ -34,9 +34,6 @@ /// @ingroup video_input /// - -/////////// -// Headers #include "config.h" #ifndef AGI_PRE @@ -46,18 +43,6 @@ #include "colorspace.h" #include "video_provider_dummy.h" - -/////////// -// Factory -// Shouldn't be needed -/*class DummyVideoProviderFactory : public VideoProviderFactory { -public: - VideoProvider *CreateProvider(wxString video,double fps=0.0) { return new DummyVideoProvider(video,fps); } - DummyVideoProviderFactory() : VideoProviderFactory(_T("dummy")) {} -} registerDummyVideo; */ - - - /// @brief Constructor /// @param _fps /// @param frames @@ -130,8 +115,6 @@ void DummyVideoProvider::Create(double _fps, int frames, int _width, int _height } } - - /// @brief Parsing constructor /// @param filename /// @@ -194,8 +177,6 @@ DummyVideoProvider::DummyVideoProvider(wxString filename) Create(fps, _frames, _width, _height, wxColour(red, green, blue), pattern); } - - /// @brief Direct constructor /// @param _fps /// @param frames @@ -208,16 +189,12 @@ DummyVideoProvider::DummyVideoProvider(double _fps, int frames, int _width, int Create(_fps, frames, _width, _height, colour, pattern); } - - /// @brief Destructor /// DummyVideoProvider::~DummyVideoProvider() { frame.Clear(); } - - /// @brief Construct a fake filename describing the video /// @param fps /// @param frames @@ -231,8 +208,6 @@ wxString DummyVideoProvider::MakeFilename(double fps, int frames, int _width, in return wxString::Format(_T("?dummy:%f:%d:%d:%d:%d:%d:%d:%s"), fps, frames, _width, _height, colour.Red(), colour.Green(), colour.Blue(), pattern?_T("c"):_T("")); } - - /// @brief Get frame /// @param n /// @return @@ -241,59 +216,3 @@ const AegiVideoFrame DummyVideoProvider::GetFrame(int n) { lastFrame = n; return frame; } - - - -/// @brief Get position -/// @return -/// -int DummyVideoProvider::GetPosition() { - return lastFrame; -} - - - -/// @brief Get frame count -/// @return -/// -int DummyVideoProvider::GetFrameCount() { - return framecount; -} - - - -/// @brief Get width -/// @return -/// -int DummyVideoProvider::GetWidth() { - return width; -} - - - -/// @brief Get height -/// @return -/// -int DummyVideoProvider::GetHeight() { - return height; -} - - - -/// @brief Get FPS -/// @return -/// -double DummyVideoProvider::GetFPS() { - return fps; -} - - - -/// @brief Get decoder name -/// -wxString DummyVideoProvider::GetDecoderName() { - return L"Dummy Video Provider"; -} - - - diff --git a/aegisub/src/video_provider_dummy.h b/aegisub/src/video_provider_dummy.h index 9d4a3d0c4..d57b42a92 100644 --- a/aegisub/src/video_provider_dummy.h +++ b/aegisub/src/video_provider_dummy.h @@ -36,18 +36,11 @@ // The dummy video provider needs a header, since it needs to be created directly as a special case - - - -/////////// -// Headers #ifndef AGI_PRE #include #endif #include "include/aegisub/video_provider.h" -#include "vfr.h" - /// DOCME /// @class DummyVideoProvider @@ -55,8 +48,6 @@ /// /// DOCME class DummyVideoProvider : public VideoProvider { -private: - /// DOCME int lastFrame; @@ -64,7 +55,7 @@ private: int framecount; /// DOCME - double fps; + agi::vfr::Framerate fps; /// DOCME int width; @@ -85,37 +76,11 @@ public: const AegiVideoFrame GetFrame(int n); static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern); - int GetPosition(); - int GetFrameCount(); - - int GetWidth(); - int GetHeight(); - double GetFPS(); - - - /// @brief DOCME - /// @return - /// - bool AreKeyFramesLoaded() { return false; }; - - /// @brief DOCME - /// @return - /// - wxArrayInt GetKeyFrames() { return wxArrayInt(); }; - - /// @brief DOCME - /// @return - /// - bool IsVFR() { return false; }; - - /// @brief DOCME - /// @return - /// - bool NeedsVFRHack() { return true; } - - /// @brief DOCME - /// - FrameRate GetTrueFrameRate() { return FrameRate(); }; - - wxString GetDecoderName(); + int GetPosition() const { return lastFrame; } + int GetFrameCount() const { return framecount; } + int GetWidth() const { return width; } + int GetHeight() const { return height; } + agi::vfr::Framerate GetFPS() const { return fps; } + std::vector GetKeyFrames() const { return std::vector(); }; + wxString GetDecoderName() const { return L"Dummy Video Provider"; } }; diff --git a/aegisub/src/video_provider_ffmpegsource.cpp b/aegisub/src/video_provider_ffmpegsource.cpp index 68472d839..91e40f3f6 100644 --- a/aegisub/src/video_provider_ffmpegsource.cpp +++ b/aegisub/src/video_provider_ffmpegsource.cpp @@ -38,8 +38,6 @@ #ifdef WITH_FFMPEGSOURCE -/////////// -// Headers #ifndef AGI_PRE #ifdef __WINDOWS__ #include @@ -79,7 +77,6 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) { // clean up variables VideoSource = NULL; - KeyFramesLoaded = false; FrameNumber = -1; ErrInfo.Buffer = FFMSErrMsg; ErrInfo.BufferSize = sizeof(FFMSErrMsg); @@ -197,7 +194,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) { FFMS_DestroyIndex(Index); Index = NULL; ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer)); - throw ErrorMsg; + throw ErrorMsg; } } @@ -249,6 +246,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) { const FFMS_FrameInfo *CurFrameData; // build list of keyframes and timecodes + std::vector TimecodesVector; for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) { CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum); if (CurFrameData == NULL) { @@ -258,47 +256,29 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) { // keyframe? if (CurFrameData->KeyFrame) - KeyFramesList.Add(CurFrameNum); + KeyFramesList.push_back(CurFrameNum); // calculate timestamp and add to timecodes vector int Timestamp = (int)((CurFrameData->PTS * TimeBase->Num) / TimeBase->Den); TimecodesVector.push_back(Timestamp); } - KeyFramesLoaded = true; - - // override already loaded timecodes? - Timecodes.SetVFR(TimecodesVector); - int OverrideTC = wxYES; - if (VFR_Output.IsLoaded()) { - OverrideTC = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION); - if (OverrideTC == wxYES) { - VFR_Input.SetVFR(TimecodesVector); - VFR_Output.SetVFR(TimecodesVector); - } - } else { // no timecodes loaded, go ahead and apply - VFR_Input.SetVFR(TimecodesVector); - VFR_Output.SetVFR(TimecodesVector); - } + Timecodes = agi::vfr::Framerate(TimecodesVector); FrameNumber = 0; } - /// @brief Close video /// void FFmpegSourceVideoProvider::Close() { FFMS_DestroyVideoSource(VideoSource); VideoSource = NULL; - KeyFramesLoaded = false; KeyFramesList.clear(); - TimecodesVector.clear(); FrameNumber = -1; + Timecodes = agi::vfr::Framerate(); CurFrame.Clear(); } - - /// @brief Get frame /// @param _n /// @return @@ -323,48 +303,4 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) { CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32); return CurFrame; } - - - -/// @brief Utility functions -/// @return -/// -int FFmpegSourceVideoProvider::GetWidth() { - return Width; -} - - -/// @brief DOCME -/// @return -/// -int FFmpegSourceVideoProvider::GetHeight() { - return Height; -} - - -/// @brief DOCME -/// @return -/// -int FFmpegSourceVideoProvider::GetFrameCount() { - return VideoInfo->NumFrames; -} - - -/// @brief DOCME -/// @return -/// -int FFmpegSourceVideoProvider::GetPosition() { - return FrameNumber; -} - - -/// @brief DOCME -/// -double FFmpegSourceVideoProvider::GetFPS() { - return double(VideoInfo->FPSNumerator) / double(VideoInfo->FPSDenominator); -} - - #endif /* WITH_FFMPEGSOURCE */ - - diff --git a/aegisub/src/video_provider_ffmpegsource.h b/aegisub/src/video_provider_ffmpegsource.h index 9f8ba3721..1ced5e125 100644 --- a/aegisub/src/video_provider_ffmpegsource.h +++ b/aegisub/src/video_provider_ffmpegsource.h @@ -34,8 +34,6 @@ /// @ingroup video_input ffms /// -/////////// -// Headers #ifdef WITH_FFMPEGSOURCE #ifndef AGI_PRE #include @@ -43,7 +41,6 @@ #include "ffmpegsource_common.h" #include "include/aegisub/video_provider.h" -#include "vfr.h" /// @class FFmpegSourceVideoProvider @@ -56,10 +53,8 @@ private: int Width; /// width in pixels int Height; /// height in pixels int FrameNumber; /// current framenumber - wxArrayInt KeyFramesList; /// list of keyframes - bool KeyFramesLoaded; /// keyframe loading state - std::vector TimecodesVector; /// list of timestamps - FrameRate Timecodes; /// vfr object + std::vector KeyFramesList; /// list of keyframes + agi::vfr::Framerate Timecodes; /// vfr object bool COMInited; /// COM initialization state AegiVideoFrame CurFrame; /// current video frame @@ -76,35 +71,22 @@ public: ~FFmpegSourceVideoProvider(); const AegiVideoFrame GetFrame(int n); - int GetPosition(); - int GetFrameCount(); - int GetWidth(); - int GetHeight(); - double GetFPS(); + int GetPosition() const { return FrameNumber; } + int GetFrameCount() const { return VideoInfo->NumFrames; } + int GetWidth() const { return Width; } + int GetHeight() const { return Height; } + agi::vfr::Framerate GetFPS() const { return Timecodes; } - /// @brief Reports keyframe status - /// @return Returns true if keyframes are loaded, false otherwise. - bool AreKeyFramesLoaded() { return KeyFramesLoaded; }; /// @brief Gets a list of keyframes /// @return Returns a wxArrayInt of keyframes. - wxArrayInt GetKeyFrames() { return KeyFramesList; }; - /// @brief Checks if source is VFR - /// @return Returns true. - bool IsVFR() { return true; }; - /// @brief Gets a VFR framerate object - /// @return Returns the framerate object. - FrameRate GetTrueFrameRate() { return Timecodes; }; - /// @brief Gets the name of the provider - /// @return Returns "FFmpegSource". - wxString GetDecoderName() { return L"FFmpegSource"; } + std::vector GetKeyFrames() const { return KeyFramesList; }; + wxString GetDecoderName() const { return L"FFmpegSource"; } /// @brief Gets the desired cache behavior. /// @return Returns true. - bool WantsCaching() { return true; } + bool WantsCaching() const { return true; } }; - - /// @class FFmpegSourceVideoProviderFactory /// @brief Creates a FFmpegSource video provider. class FFmpegSourceVideoProviderFactory : public VideoProviderFactory { @@ -115,7 +97,4 @@ public: VideoProvider *CreateProvider(wxString video) { return new FFmpegSourceVideoProvider(video); } }; - #endif /* WITH_FFMPEGSOURCE */ - - diff --git a/aegisub/src/video_provider_manager.cpp b/aegisub/src/video_provider_manager.cpp index 62220ba91..12766dfbf 100644 --- a/aegisub/src/video_provider_manager.cpp +++ b/aegisub/src/video_provider_manager.cpp @@ -34,9 +34,6 @@ /// @ingroup video_input /// - -/////////// -// Headers #include "config.h" #include @@ -44,7 +41,7 @@ #include "compat.h" #include "main.h" #include "options.h" -#include "vfr.h" + #ifdef WITH_AVISYNTH #include "video_provider_avs.h" #endif diff --git a/aegisub/src/video_provider_quicktime.cpp b/aegisub/src/video_provider_quicktime.cpp index 55f779a60..60230250e 100644 --- a/aegisub/src/video_provider_quicktime.cpp +++ b/aegisub/src/video_provider_quicktime.cpp @@ -54,8 +54,6 @@ #define MacOffsetRect OffsetRect #endif - - /// @brief DOCME /// @param filename /// @@ -99,8 +97,6 @@ QuickTimeVideoProvider::QuickTimeVideoProvider(wxString filename) { } } - - /// @brief DOCME /// QuickTimeVideoProvider::~QuickTimeVideoProvider() { @@ -108,8 +104,6 @@ QuickTimeVideoProvider::~QuickTimeVideoProvider() { DeInitQuickTime(); } - - /// @brief DOCME /// void QuickTimeVideoProvider::Close() { @@ -123,15 +117,10 @@ void QuickTimeVideoProvider::Close() { DisposeHandle(in_dataref); in_dataref = NULL; - keyframes.Clear(); + keyframes.clear(); qt_timestamps.clear(); } - - - - - /// @brief DOCME /// @param _filename /// @@ -175,28 +164,11 @@ void QuickTimeVideoProvider::LoadVideo(const wxString _filename) { throw wxString(_T("QuickTime video provider: failed to index file")); // ask about vfr override etc - vfr_fps.SetVFR(timecodes); - int override_tc = wxYES; - if (VFR_Output.IsLoaded()) { - override_tc = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION); - if (override_tc == wxYES) { - VFR_Input.SetVFR(timecodes); - VFR_Output.SetVFR(timecodes); - } - } else { // no timecodes loaded, go ahead and apply - VFR_Input.SetVFR(timecodes); - VFR_Output.SetVFR(timecodes); - } - - // set assumed "cfr" fps (dunno if this is actually used anywhere) - double len_s = (double)GetMovieDuration(movie) / (double)GetMovieTimeScale(movie); - assumed_fps = (double)num_frames / len_s; + vfr_fps = agi::vfr::Framerate(timecodes); cur_fn = 0; } - - /// @brief DOCME /// @return /// @@ -237,8 +209,6 @@ std::vector QuickTimeVideoProvider::IndexFile() { return timecodes; } - - /// @brief DOCME /// @param n /// @return @@ -283,76 +253,4 @@ const AegiVideoFrame QuickTimeVideoProvider::GetFrame(int n) { return dst_frame; } - - - - -/// @brief Utility functions -/// @return -/// -int QuickTimeVideoProvider::GetWidth() { - return w; -} - - -/// @brief DOCME -/// @return -/// -int QuickTimeVideoProvider::GetHeight() { - return h; -} - - -/// @brief DOCME -/// @return -/// -int QuickTimeVideoProvider::GetFrameCount() { - return num_frames; -} - - -/// @brief DOCME -/// @return -/// -int QuickTimeVideoProvider::GetPosition() { - return cur_fn; -} - - -/// @brief DOCME -/// @return -/// -double QuickTimeVideoProvider::GetFPS() { - return assumed_fps; -} - - -/// @brief DOCME -/// @return -/// -bool QuickTimeVideoProvider::AreKeyFramesLoaded() { - if (keyframes.GetCount() > 0) - return true; - else - return false; -} - - -/// @brief DOCME -/// @return -/// -wxArrayInt QuickTimeVideoProvider::GetKeyFrames() { - return keyframes; -} - - -/// @brief DOCME -/// -FrameRate QuickTimeVideoProvider::GetTrueFrameRate() { - return vfr_fps; -} - - #endif /* WITH_QUICKTIME */ - - diff --git a/aegisub/src/video_provider_quicktime.h b/aegisub/src/video_provider_quicktime.h index 2a8b45d9a..a8eb40fd1 100644 --- a/aegisub/src/video_provider_quicktime.h +++ b/aegisub/src/video_provider_quicktime.h @@ -49,8 +49,6 @@ #include "include/aegisub/video_provider.h" -#include "vfr.h" - /// DOCME /// @class QuickTimeVideoProvider @@ -58,47 +56,42 @@ /// /// DOCME class QuickTimeVideoProvider : public VideoProvider, QuickTimeProvider { -private: + /// source object + Movie movie; - /// DOCME - Movie movie; // source object + /// render buffer + GWorldPtr gw; - /// DOCME - GWorldPtr gw; // render buffer - - /// DOCME - Handle in_dataref; // input data handle + /// input data handle + Handle in_dataref; /// DOCME - /// DOCME - int w, h; // width/height + /// width/height + int w, h; - /// DOCME - int num_frames; // length of file in frames + /// length of file in frames + int num_frames; - /// DOCME - int cur_fn; // current frame number + /// current frame number + int cur_fn; - /// DOCME - FrameRate vfr_fps; // vfr framerate + /// vfr framerate + Framerate vfr_fps; - /// DOCME - double assumed_fps; // average framerate + /// list of keyframes + std::vector keyframes; - /// DOCME - wxArrayInt keyframes; // list of keyframes - - /// DOCME - std::vector qt_timestamps; // qt timestamps (used for seeking) + /// qt timestamps (used for seeking) + std::vector qt_timestamps; - /// DOCME - OSErr qt_err; // quicktime error code + /// quicktime error code + OSErr qt_err; - /// DOCME - wxString errmsg; // aegisub error message + /// aegisub error message + wxString errmsg; void LoadVideo(const wxString filename); std::vector IndexFile(); @@ -109,34 +102,18 @@ public: ~QuickTimeVideoProvider(); const AegiVideoFrame GetFrame(int n); - int GetPosition(); - int GetFrameCount(); - int GetWidth(); - int GetHeight(); - double GetFPS(); - - /// @brief DOCME - /// @return - /// - bool IsVFR() { return true; }; - FrameRate GetTrueFrameRate(); - wxArrayInt GetKeyFrames(); - bool QuickTimeVideoProvider::AreKeyFramesLoaded(); - - /// @brief DOCME - /// @return - /// - wxString GetDecoderName() { return L"QuickTime"; }; - - /// @brief DOCME - /// @return - /// - bool WantsCaching() { return true; }; + int GetPosition() const { return cur_fn; } + int GetFrameCount() const { return num_frames; } + int GetWidth() const { return w; } + int GetHeight() const { return h; } + agi::vfr::Framerate GetFPS() const { return vfr_fps; } + std::vector GetKeyFrames() const { return keyframes; }; + wxString GetDecoderName() const { return L"QuickTime"; }; + bool WantsCaching() const { return true; }; + wxString GetWarning() const { return errmsg; } }; - - /// DOCME /// @class QuickTimeVideoProviderFactory /// @brief DOCME @@ -151,7 +128,4 @@ public: VideoProvider *CreateProvider(wxString video) { return new QuickTimeVideoProvider(video); } }; - #endif /* WITH_QUICKTIME */ - - diff --git a/aegisub/src/video_provider_yuv4mpeg.cpp b/aegisub/src/video_provider_yuv4mpeg.cpp index 5d7af1785..02ac91b34 100644 --- a/aegisub/src/video_provider_yuv4mpeg.cpp +++ b/aegisub/src/video_provider_yuv4mpeg.cpp @@ -309,6 +309,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector& tags) { fps_rat.den = t_fps_den; pixfmt = t_pixfmt != Y4M_PIXFMT_NONE ? t_pixfmt : Y4M_PIXFMT_420JPEG; imode = t_imode != Y4M_ILACE_NOTSET ? t_imode : Y4M_ILACE_UNKNOWN; + fps = double(fps_rat.num) / fps_rat.den; inited = true; } } @@ -430,27 +431,3 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) { return dst_frame; } - - - -// Utility functions -int YUV4MPEGVideoProvider::GetWidth() { - return w; -} - -int YUV4MPEGVideoProvider::GetHeight() { - return h; -} - -int YUV4MPEGVideoProvider::GetFrameCount() { - return num_frames; -} - -int YUV4MPEGVideoProvider::GetPosition() { - return cur_fn; -} - -double YUV4MPEGVideoProvider::GetFPS() { - return double(fps_rat.num) / double(fps_rat.den); -} - diff --git a/aegisub/src/video_provider_yuv4mpeg.h b/aegisub/src/video_provider_yuv4mpeg.h index 33a178049..9a59e613c 100644 --- a/aegisub/src/video_provider_yuv4mpeg.h +++ b/aegisub/src/video_provider_yuv4mpeg.h @@ -34,8 +34,6 @@ /// @ingroup video_input /// - - #include "include/aegisub/video_provider.h" #ifndef AGI_PRE #include @@ -46,16 +44,12 @@ #include #endif - /// the maximum allowed header length, in bytes #define YUV4MPEG_HEADER_MAXLEN 128 - - /// @class YUV4MPEGVideoProvider /// @brief Implements reading of YUV4MPEG uncompressed video files class YUV4MPEGVideoProvider : public VideoProvider { -private: /// Pixel formats enum Y4M_PixelFormat { Y4M_PIXFMT_NONE = -1, /// not set/unknown @@ -131,6 +125,8 @@ private: int den; /// denominator } fps_rat; /// framerate + agi::vfr::Framerate fps; + /// a list of byte positions detailing where in the file /// each frame header can be found std::vector seek_table; @@ -151,20 +147,13 @@ public: ~YUV4MPEGVideoProvider(); const AegiVideoFrame GetFrame(int n); - int GetPosition(); - int GetFrameCount(); - int GetWidth(); - int GetHeight(); - double GetFPS(); - - bool AreKeyFramesLoaded() { return false; } - wxArrayInt GetKeyFrames() { return wxArrayInt(); } - bool IsVFR() { return false; }; - FrameRate GetTrueFrameRate() { return FrameRate(); } - wxString GetDecoderName() { return L"YUV4MPEG"; } - bool WantsCaching() { return true; } + int GetPosition() const { return cur_fn; } + int GetFrameCount() const { return num_frames; } + int GetWidth() const { return w; } + int GetHeight() const { return h; } + agi::vfr::Framerate GetFPS() const { return fps; } + std::vector GetKeyFrames() const { return std::vector(); }; + wxString GetDecoderName() const { return L"YU4MPEG"; }; + bool WantsCaching() const { return true; }; }; - - - diff --git a/aegisub/src/video_slider.cpp b/aegisub/src/video_slider.cpp index 9725a8a85..bb0f2477f 100644 --- a/aegisub/src/video_slider.cpp +++ b/aegisub/src/video_slider.cpp @@ -49,7 +49,6 @@ #include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" -#include "vfr.h" #include "video_context.h" #include "video_display.h" #include "video_slider.h" @@ -226,8 +225,8 @@ void VideoSlider::OnMouse(wxMouseEvent &event) { if (canDrag) { // Shift click to snap to keyframe if (shift && Display) { - wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); - int keys = KeyFrames.Count(); + std::vector KeyFrames = VideoContext::Get()->GetKeyFrames(); + int keys = KeyFrames.size(); int clickedFrame = GetValueAtX(x); int closest = 0; int cur; @@ -332,8 +331,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) { // Jump to next sub boundary if (direction != 0) { - int target1 = VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true); - int target2 = VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),false); + int target1 = VideoContext::Get()->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START); + int target2 = VideoContext::Get()->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END); bool drawn = false; // Forward @@ -376,8 +375,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) { // Prepare int prevKey = 0; int nextKey = VideoContext::Get()->GetLength()-1; - wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); - int keys = KeyFrames.Count(); + std::vector KeyFrames = VideoContext::Get()->GetKeyFrames(); + int keys = KeyFrames.size(); int cur = VideoContext::Get()->GetFrameN(); int i; int temp; @@ -481,8 +480,8 @@ void VideoSlider::DrawImage(wxDC &destdc) { int curX; if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) { dc.SetPen(wxPen(shad)); - wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); - int keys = KeyFrames.Count(); + std::vector KeyFrames = VideoContext::Get()->GetKeyFrames(); + int keys = KeyFrames.size(); for (int i=0;itype != DRAG_ORIGIN) { - int time = VFR_Output.GetTimeAtFrame(frameNumber,true,true) - feature->line->Start.GetMS(); + int time = VideoContext::Get()->TimeAtFrame(frameNumber) - feature->line->Start.GetMS(); int change = time - feature->time; for (sel_iterator cur = selectedFeatures.begin(); cur != selectedFeatures.end(); ++cur) {