From 3518f381a72807bb1b33d5f2de8258471e6b673a Mon Sep 17 00:00:00 2001 From: Alysson Souza Date: Sun, 26 Aug 2007 00:00:37 +0000 Subject: [PATCH] Added support for reading keyframes from xvid pass files Originally committed to SVN as r1535. --- aegisub/Makefile.am | 1 + aegisub/changelog.txt | 3 +- aegisub/frame_main.cpp | 95 +-------------------- aegisub/frame_main.h | 2 - aegisub/frame_main_events.cpp | 20 +++-- aegisub/keyframe.cpp | 150 ++++++++++++++++++++++++++++++++++ aegisub/keyframe.h | 52 ++++++++++++ 7 files changed, 222 insertions(+), 101 deletions(-) create mode 100644 aegisub/keyframe.cpp create mode 100644 aegisub/keyframe.h diff --git a/aegisub/Makefile.am b/aegisub/Makefile.am index 91cab5a5d..11f193221 100644 --- a/aegisub/Makefile.am +++ b/aegisub/Makefile.am @@ -175,6 +175,7 @@ aegisub_SOURCES = \ hotkeys.cpp \ idle_field_event.cpp \ kana_table.cpp \ + keyframe.cpp \ main.cpp \ md5.c \ mkv_wrap.cpp \ diff --git a/aegisub/changelog.txt b/aegisub/changelog.txt index b49c051ec..0b412bd6b 100644 --- a/aegisub/changelog.txt +++ b/aegisub/changelog.txt @@ -153,7 +153,7 @@ Please visit http://aegisub.net to download latest version - Frame number is now the default box on the "go to" dialog. (AMZ) - Added "Video Formats" to "Open Audio"'s file selector, so you can open audio directly from video files (regardless of whether they're loaded or not). This has always worked, but it was never explicit. (AMZ) - Added a "Scale Border and Shadow" check box to script properties dialog. (AMZ) -- Fixed display of end frames on the subtitles grid, when set to frame mode. (demi) +- Fixed display of end frames on the subtitles grid, when set to frame mode. (demi`) - Treat comments inside {}'s as plain text, not as overrides; Also, don't assume override blocks start with a backslash, even if they probably should (Dansolo) - Removed FexTracker due to licensing problems; there are plans to implement a new motion tracker in its place (jfs) - Changed translation assistent to use Scintilla text controls to avoid several issues, including Right-To-Left text entry. (AMZ) @@ -161,6 +161,7 @@ Please visit http://aegisub.net to download latest version - Added a "new window" command to the file menu, to launch a new instance of Aegisub. (AMZ) - Added "Effect" field to the Select Lines dialog. (demi`) - Added a new "Video Details" dialog, that lists some information regarding the currently open video. (demi`) +- Added support for reading keyframes from xvid pass files. (demi`) = 1.10 beta - 2006.08.07 =========================== diff --git a/aegisub/frame_main.cpp b/aegisub/frame_main.cpp index a7f01d9e1..dfd0e1250 100644 --- a/aegisub/frame_main.cpp +++ b/aegisub/frame_main.cpp @@ -69,6 +69,7 @@ #include "dialog_version_check.h" #include "dialog_detached_video.h" #include "standard_paths.h" +#include "keyframe.h" ///////////////////////// @@ -836,7 +837,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) { } // Keyframes - LoadKeyframes(curSubsKeyframes); + KeyFrameFile::Load(curSubsKeyframes); // Audio if (curSubsAudio != audioBox->audioName) { @@ -1057,98 +1058,6 @@ void FrameMain::LoadVFR(wxString filename) { } -////////////////// -// Load Keyframes -void FrameMain::LoadKeyframes(wxString filename) { - // Unload - if (filename.IsEmpty()) { - wxArrayInt keyFrames; - keyFrames.Empty(); - VideoContext::Get()->CloseOverKeyFrames(); - videoBox->videoSlider->Refresh(); - audioBox->audioDisplay->Update(); - Refresh(); - return; - } - - // Load - try { - // Open file - wxArrayInt keyFrames; - keyFrames.Empty(); - TextFileReader file(filename,_T("ASCII")); - - // Read header - wxString cur = file.ReadLineFromFile(); - if (cur != _T("# keyframe format v1")) throw _T("Invalid keyframes file, missing header."); - cur = file.ReadLineFromFile(); - if (cur.Left(4) != _T("fps ")) throw _T("Invalid keyframes file, missing FPS."); - cur = cur.Mid(4); - double fps; - cur.ToDouble(&fps); - if (fps == 0.0) throw _T("Invalid FPS."); - - // Read lines - while (file.HasMoreLines()) { - cur = file.ReadLineFromFile(); - if (!cur.IsEmpty() && cur.IsNumber()) { - long temp; - cur.ToLong(&temp); - keyFrames.Add(temp); - } - } - - // Set keyframes - VideoContext::Get()->SetOverKeyFrames(keyFrames); - VideoContext::Get()->SetKeyFramesName(filename); - - // Set FPS - if (!VideoContext::Get()->IsLoaded()) { - VideoContext::Get()->SetFPS(fps); - VFR_Input.SetCFR(fps); - if (!VFR_Output.IsLoaded()) VFR_Output.SetCFR(fps); - } - - // Add to recent - Options.AddToRecentList(filename,_T("Recent keyframes")); - - // Refresh display - Refresh(); - audioBox->audioDisplay->Update(); - } - - // Fail - catch (const wchar_t *error) { - wxString err(error); - wxMessageBox(err, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, this); - } - catch (...) { - wxMessageBox(_T("Unknown error"), _T("Error opening keyframes file"), wxOK | wxICON_ERROR, this); - } -} - - -////////////////// -// Save Keyframes -void FrameMain::SaveKeyframes(wxString filename) { - // Get keyframes - wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames(); - - // Write header - TextFileWriter file(filename,_T("ASCII")); - file.WriteLineToFile(_T("# keyframe format v1")); - file.WriteLineToFile(wxString::Format(_T("fps %f"),VideoContext::Get()->GetFPS())); - - // Write keyframes - for (unsigned int i=0;ivideoSlider->Refresh(); + audioBox->audioDisplay->Update(); + Refresh(); } @@ -759,20 +763,26 @@ void FrameMain::OnCloseVFR(wxCommandEvent &event) { void FrameMain::OnOpenKeyframes (wxCommandEvent &event) { // Pick file wxString path = Options.AsText(_T("Last open keyframes path")); - wxString filename = wxFileSelector(_T("Select the Keyframes file to open"),path,_T(""),_T(".txt"),_T("Text files (*.txt)|*.txt"),wxFD_FILE_MUST_EXIST | wxFD_OPEN); + wxString filename = wxFileSelector(_T("Select the keyframes file to open"),path,_T(""),_T(".txt"),_T("All supported formats (*.txt, *.pass)|*.txt;*.pass|All files (*.*)|*.*"),wxFD_FILE_MUST_EXIST | wxFD_OPEN); if (filename.IsEmpty()) return; Options.SetText(_T("Last open keyframes path"),filename); Options.Save(); // Load - LoadKeyframes(filename); + KeyFrameFile::Load(filename); + videoBox->videoSlider->Refresh(); + audioBox->audioDisplay->Update(); + Refresh(); } /////////////////// // Close keyframes void FrameMain::OnCloseKeyframes (wxCommandEvent &event) { - LoadKeyframes(_T("")); + VideoContext::Get()->CloseOverKeyFrames(); + videoBox->videoSlider->Refresh(); + audioBox->audioDisplay->Update(); + Refresh(); } @@ -787,7 +797,7 @@ void FrameMain::OnSaveKeyframes (wxCommandEvent &event) { Options.Save(); // Save - SaveKeyframes(filename); + KeyFrameFile::Save(filename); } diff --git a/aegisub/keyframe.cpp b/aegisub/keyframe.cpp new file mode 100644 index 000000000..5760b55b1 --- /dev/null +++ b/aegisub/keyframe.cpp @@ -0,0 +1,150 @@ +// Copyright (c) 2007, Alysson Souza e Silva +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + +/////////// +// Headers +#include "video_context.h" +#include "keyframe.h" +#include "text_file_reader.h" +#include "text_file_writer.h" +#include "options.h" +#include "vfr.h" + + +////////////////// +// Load Keyframes +void KeyFrameFile::Load(wxString filename) { + // Load + try { + // Open file + wxArrayInt keyFrames; + keyFrames.Empty(); + TextFileReader file(filename,_T("ASCII")); + + wxString cur = file.ReadLineFromFile(); + // Detect type + if (cur == _T("# keyframe format v1")) { OpenAegiKeyFrames(file, keyFrames); } + else if (cur.StartsWith(_T("# XviD 2pass stat file"))) { OpenXviDKeyFrames(file, keyFrames); } + else { throw(_T("Invalid keyframes file.")); } + + // Set keyframes + VideoContext::Get()->SetOverKeyFrames(keyFrames); + VideoContext::Get()->SetKeyFramesName(filename); + + // Add to recent + Options.AddToRecentList(filename,_T("Recent keyframes")); + } + // Fail + catch (const wchar_t *error) { + wxString err(error); + wxMessageBox(err, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); + } + catch (...) { + wxMessageBox(_T("Unknown error"), _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); + } +} + + +////////////////// +// Save Keyframes +void KeyFrameFile::Save(wxString filename) { + // Get keyframes + wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames(); + + // Write header + TextFileWriter file(filename,_T("ASCII")); + file.WriteLineToFile(_T("# keyframe format v1")); + file.WriteLineToFile(wxString::Format(_T("fps %f"),VideoContext::Get()->GetFPS())); + + // Write keyframes + for (unsigned int i=0;iIsLoaded()) { + VideoContext::Get()->SetFPS(fps); + VFR_Input.SetCFR(fps); + if (!VFR_Output.IsLoaded()) VFR_Output.SetCFR(fps); + } + + // Read lines + while (file.HasMoreLines()) { + cur = file.ReadLineFromFile(); + if (!cur.IsEmpty() && cur.StartsWith(_T("#")) && cur.IsNumber()) { + long temp; + cur.ToLong(&temp); + keyFrames.Add(temp); + } + } +} + +/////////////////// +// XviD stats file +void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) +{ + wxString cur = file.ReadLineFromFile(); + int count = 0; + + // Read lines + while (file.HasMoreLines()) { + cur = file.ReadLineFromFile(); + wxString teste = cur.Left(1); + if (cur.StartsWith(_T("i"))) { + keyFrames.Add(count); + } + if (cur.StartsWith(_T("i")) || cur.StartsWith(_T("p")) || cur.StartsWith(_T("b"))) { + count++; + } + } +} diff --git a/aegisub/keyframe.h b/aegisub/keyframe.h new file mode 100644 index 000000000..fe5feb4e3 --- /dev/null +++ b/aegisub/keyframe.h @@ -0,0 +1,52 @@ +// Copyright (c) 2007, Alysson Souza e Silva +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +/////////// +// Headers +#include "text_file_reader.h" + + +///////// +// Class +class KeyFrameFile +{ +public: + static void Load(wxString filename); + static void Save(wxString filename); +private: + static void OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); + static void OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); +};