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) {