Added support for reading keyframes from xvid pass files

Originally committed to SVN as r1535.
This commit is contained in:
Alysson Souza 2007-08-26 00:00:37 +00:00
parent 4f689ac204
commit 3518f381a7
7 changed files with 222 additions and 101 deletions

View file

@ -175,6 +175,7 @@ aegisub_SOURCES = \
hotkeys.cpp \
idle_field_event.cpp \
kana_table.cpp \
keyframe.cpp \
main.cpp \
md5.c \
mkv_wrap.cpp \

View file

@ -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 ===========================

View file

@ -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;i<keyFrames.Count();i++) {
file.WriteLineToFile(wxString::Format(_T("%i"),keyFrames[i]));
}
// Add to recent
Options.AddToRecentList(filename,_T("Recent keyframes"));
}
/////////////
// Open help
void FrameMain::OpenHelp(wxString page) {

View file

@ -242,8 +242,6 @@ private:
void LoadVideo(wxString filename,bool autoload=false);
void LoadAudio(wxString filename,bool FromVideo=false);
void LoadVFR(wxString filename);
void LoadKeyframes(wxString filename);
void SaveKeyframes(wxString filename);
void LoadSubtitles(wxString filename,wxString charset=_T(""));
bool SaveSubtitles(bool saveas=false,bool withCharset=false);
int TryToCloseSubs(bool enableCancel=true);

View file

@ -84,6 +84,7 @@
#include "dialog_associations.h"
#include "standard_paths.h"
#include "dialog_video_details.h"
#include "keyframe.h"
////////////////////
@ -500,7 +501,10 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
int number = event.GetId()-Menu_Keyframes_Recent;
wxString key = _T("Recent Keyframes #") + wxString::Format(_T("%i"),number+1);
LoadKeyframes(Options.AsText(key));
KeyFrameFile::Load(Options.AsText(key));
videoBox->videoSlider->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);
}

150
aegisub/keyframe.cpp Normal file
View file

@ -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;i<keyFrames.Count();i++) {
file.WriteLineToFile(wxString::Format(_T("%i"),keyFrames[i]));
}
// Add to recent
Options.AddToRecentList(filename,_T("Recent keyframes"));
}
//////////////////////////
// Aegisub keyframes file
void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames)
{
double fps;
wxString cur = file.ReadLineFromFile();
// Read header
if (cur.Left(4) != _T("fps ")) throw _T("Invalid keyframes file, missing FPS.");
cur = cur.Mid(4);
cur.ToDouble(&fps);
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);
}
// 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++;
}
}
}

52
aegisub/keyframe.h Normal file
View file

@ -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);
};