Rewrite VFR handling in Aegisub.

Kill vfr.h and vfr.cpp and use the libaegisub versions of them instead.

Rather than the globals VFR_Input and VFR_Output, everything related to
frame rate is now part of the video context. Most things which used to
use VFR_Output now call VideoContext::TimeAtFrame etc.; video providers,
rather than modifying VFR_Input directly, now have getters for their
frame rates which VideoContext calls. Read-only public access to
VFR_Input and VFR_Output are still provided (hopefully temporarily) for
a few things which were awkward to do through VideoContext.

The Avisynth provider now might correctly handle VFR MKVs which can be
opened with DirectShowSource but not DSS2.

Rework keyframe handling as well, so that it continues to match the vfr
handling in design and implementation.

Originally committed to SVN as r4662.
This commit is contained in:
Thomas Goyne 2010-07-08 04:29:04 +00:00
parent 9322f95071
commit acba2c6b63
62 changed files with 680 additions and 2616 deletions

View File

@ -1011,14 +1011,6 @@
RelativePath="..\..\src\vector2d.h"
>
</File>
<File
RelativePath="..\..\src\vfr.cpp"
>
</File>
<File
RelativePath="..\..\src\vfr.h"
>
</File>
</Filter>
<Filter
Name="Dialogs"

View File

@ -181,7 +181,7 @@ Framerate::Framerate(std::vector<int> 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<ifstream> 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<int>(*file, encoding), line_iterator<int>(), 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 ") {

View File

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

View File

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

View File

@ -45,7 +45,6 @@
#include "ass_dialogue.h"
#include "ass_override.h"
#include "utils.h"
#include "vfr.h"
AssDialogue::AssDialogue()
: Comment(false)

View File

@ -60,7 +60,6 @@
#include "text_file_writer.h"
#include "utils.h"
#include "version.h"
#include "vfr.h"
/// @brief AssFile constructor
AssFile::AssFile () {

View File

@ -50,7 +50,6 @@
#include "ass_time.h"
#include "utils.h"
#include "vfr.h"
/// @brief AssTime constructors

View File

@ -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<int> 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<nKeys;i++) {
int cur = KeyFrames[i];
if (cur >= 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<int> keyFrames = VideoContext::Get()->GetKeyFrames();
int frame;
for (unsigned int i=0;i<keyFrames.Count();i++) {
for (unsigned int i=0;i<keyFrames.size();i++) {
frame = keyFrames[i];
if (!start) frame--;
if (frame < 0) frame = 0;
keyMS = VFR_Output.GetTimeAtFrame(frame,start);
keyMS = VideoContext::Get()->TimeAtFrame(frame,start ? agi::vfr::START : agi::vfr::END);
//if (start) keyX++;
if (GetXAtMS(keyMS) >= 0 && GetXAtMS(keyMS) < w) boundaries.Add(keyMS);
}

View File

@ -34,12 +34,8 @@
/// @ingroup audio_ui
///
#pragma once
///////////
// Headers
#ifndef AGI_PRE
#include <stdint.h>
@ -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
};

View File

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

View File

@ -53,6 +53,7 @@
#endif
class wxWindow;
namespace agi { namespace vfr { class Framerate; } }
/// DOCME

View File

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

View File

@ -37,8 +37,6 @@
#pragma once
////////////
// Includes
#ifndef AGI_PRE
#include <list>
#include <vector>
@ -49,13 +47,11 @@
#include "selection_controller.h"
//////////////
// Prototypes
class AssEntry;
class AssDialogue;
class SubsEditBox;
class FrameMain;
class VideoContext;
/// DOCME
typedef std::list<AssEntry*>::iterator entryIter;
@ -71,8 +67,6 @@ typedef SelectionListener<AssDialogue> SubtitleSelectionListener;
///
/// DOCME
class BaseGrid : public wxWindow, public BaseSelectionController<AssDialogue> {
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
///

View File

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

View File

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

View File

@ -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;i<len;i++) {
StyleList->Check(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;i<len;i++) {
StyleList->Check(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;i<n;i++) {
if (abs(KeyFrames[i]-frame) < abs(closest-frame)) {
closest = KeyFrames[i];
@ -358,8 +327,6 @@ int DialogTimingProcessor::GetClosestKeyFrame(int frame) {
return closest;
}
/// @brief Check if style is listed
/// @param styleName
/// @return
@ -372,9 +339,7 @@ bool DialogTimingProcessor::StyleOK(wxString styleName) {
return false;
}
/// @brief Sort dialogues
/// @brief Sort dialogues
///
void DialogTimingProcessor::SortDialogues() {
// Copy from original to temporary list
@ -400,8 +365,6 @@ void DialogTimingProcessor::SortDialogues() {
}
}
/// @brief Gets sorted dialogue
/// @param n
/// @return
@ -415,12 +378,9 @@ AssDialogue *DialogTimingProcessor::GetSortedDialogue(int n) {
}
}
/// @brief Actually process subtitles
///
void DialogTimingProcessor::Process() {
// Sort rows
SortDialogues();
int rows = Sorted.size();
@ -539,8 +499,9 @@ void DialogTimingProcessor::Process() {
// Keyframe snapping
if (keysEnable->IsChecked()) {
// 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();
}

View File

@ -34,11 +34,6 @@
/// @ingroup tools_ui
///
///////////
// Headers
#ifndef AGI_PRE
#include <vector>
@ -51,33 +46,24 @@
#include <wx/textctrl.h>
#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<int> 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<AssDialogue*> 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
};

View File

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

View File

@ -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<AssDialogue*>(*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;
}

View File

@ -35,7 +35,7 @@
///
#include "ass_export_filter.h"
#include "vfr.h"
#include <libaegisub/vfr.h>
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

View File

@ -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<AssDialogue*>(*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;

View File

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

View File

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

View File

@ -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;i<n;i++) {
frame = keyframes[i];
VideoContext *con = VideoContext::Get();
if (!con->IsLoaded() || !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;i<sel.Count();i++) {
cur = SubsGrid->GetDialogue(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<int> &keyframes = con->GetKeyFrames();
if (curFrame < keyframes.front()) {
next = keyframes.front();
}
else if (curFrame >= keyframes.back()) {
prev = keyframes.back();
next = con->GetLength();
}
else {
std::vector<int>::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;i<sel.Count();i++) {
cur = SubsGrid->GetDialogue(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;i<n;i++) {
cur = SubsGrid->GetDialogue(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;i<n;i++) {
cur = SubsGrid->GetDialogue(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

View File

@ -34,16 +34,10 @@
/// @ingroup main_headers video_input
///
#pragma once
//////////
// Headers
#include "aegisub.h"
#include "vfr.h"
#include "video_frame.h"
#include <libaegisub/vfr.h>
/// @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<int> 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<int> 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;
};

View File

@ -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<int> KeyFrameFile::Load(wxString filename) {
try {
// Open file
wxArrayInt keyFrames;
keyFrames.Empty();
std::vector<int> 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<int>();
}
/// @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<int> 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;i<keyFrames.Count();i++) {
for (unsigned int i=0;i<keyFrames.size();i++) {
file.WriteLineToFile(wxString::Format(_T("%i"),keyFrames[i]));
}
// Add to recent
config::mru->Add("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<int>& 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<int>& 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<int>& 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<int>& 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();
}
}

View File

@ -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<int> Load(wxString filename);
static void Save(wxString filename, std::vector<int> 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<int>& keyFrames);
static void OpenXviDKeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
static void OpenDivXKeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
static void Openx264KeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
};

View File

@ -280,7 +280,6 @@ bool AegisubApp::OnInit() {
///
int AegisubApp::OnExit() {
SubtitleFormat::DestroyFormats();
VideoContext::Clear();
delete plugins;
delete config::opt;
delete config::mru;

View File

@ -34,9 +34,6 @@
/// @ingroup video_input
///
///////////
// Headers
#include "config.h"
#ifndef AGI_PRE
@ -44,6 +41,7 @@
#include <stdint.h>
#include <algorithm>
#include <iterator>
#include <wx/filename.h>
#include <wx/tokenzr.h>
@ -53,6 +51,7 @@
#include "ass_file.h"
#include "ass_time.h"
#include "dialog_progress.h"
#include <libaegisub/vfr.h>
#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<std::vector<double>::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<frames;i++) {
t1 = timecodes[i];
t2 = timecodes[i-1];
int delta = abs(int(t1 - t2 - estimateCFR));
if (delta > 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<int> times;
for (int i=0;i<frames;i++) times.push_back(int(timecodes[i]+0.5));
target.SetVFR(times);
}
std::vector<int> times;
times.reserve(timecodes.size());
std::transform(timecodes.begin(), timecodes.end(), std::back_inserter(times), &mkv_round);
target = agi::vfr::Framerate(times);
}

View File

@ -34,11 +34,6 @@
/// @ingroup video_input
///
///////////
// Headers
#ifndef AGI_PRE
#include <stdint.h>
#include <stdio.h>
@ -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

View File

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

View File

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

View File

@ -34,11 +34,6 @@
/// @ingroup main_ui
///
////////////
// Includes
#ifndef AGI_PRE
#include <fstream>
#include <iostream>
@ -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<AssEntry*>::iterator entryIter;
/// DOCME
/// @class SubtitlesGrid
/// @brief DOCME

View File

@ -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*> 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<AssEntry*> &list, std::list<AssEn
}
}
/// @brief Split and merge lines so there are no overlapping lines
///
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
@ -580,8 +530,6 @@ void SubtitleFormat::RecombineOverlaps() {
}
}
/// @brief Merge identical lines that follow each other
///
void SubtitleFormat::MergeIdentical() {
@ -608,6 +556,3 @@ void SubtitleFormat::MergeIdentical() {
}
}
}

View File

@ -34,12 +34,8 @@
/// @ingroup subtitle_io
///
#pragma once
///////////
// Headers
#ifndef AGI_PRE
#include <list>
@ -49,22 +45,15 @@
#include <libaegisub/exception.h>
//////////////
// 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<SubtitleFormat*> formats;
@ -82,7 +70,6 @@ private:
static bool loaded;
protected:
/// DOCME
struct FPSRational {
@ -96,7 +83,6 @@ protected:
bool smpte_dropframe;
};
/// DOCME
std::list<AssEntry*> *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")

View File

@ -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 = &cfr;
agi::vfr::Framerate cfr;
const agi::vfr::Framerate *rate = &cfr;
// 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 = &cfr;
agi::vfr::Framerate cfr;
const agi::vfr::Framerate *rate = &cfr;
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<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
AssDialogue *current = dynamic_cast<AssDialogue*>(*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();
}

View File

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

View File

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

View File

@ -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 <csri/csri.h>
#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

View File

@ -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() {
}
}
}

View File

@ -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 <wx/filename.h>
#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 <fps>' line");
else {
if (!curLine.Mid(6).ToDouble(&AverageFrameRate) || AverageFrameRate <= 0) throw _T("Invalid 'Assume <fps>' 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<Frame.size();i++) {
file.WriteLineToFile(wxString::Format(_T("%f"),(float)Frame[i]));
}
}
/// @brief Unload
void FrameRate::Unload () {
FrameRateType = NONE;
AverageFrameRate = 0;
last_time = 0;
last_frame = 0;
Clear();
loaded = false;
vfrFile = _T("");
}
/// @brief Sets to CFR
/// @param fps
void FrameRate::SetCFR(double fps) {
Unload();
loaded = true;
FrameRateType = CFR;
AverageFrameRate = fps;
}
/// @brief Sets to VFR
/// @param newTimes
void FrameRate::SetVFR(std::vector<int> 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<int> 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;

View File

@ -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 <list>
#include <vector>
#include <wx/dynarray.h>
#include <wx/string.h>
#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<int> 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<int> 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<int> GetFrameTimeList() const;
bool operator==(FrameRate const& rgt);
};
extern FrameRate VFR_Output;
extern FrameRate VFR_Input;

View File

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

View File

@ -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 <libaegisub/access.h>
#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<VideoDisplay*>::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<VideoDisplay*>::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);
}

View File

@ -38,6 +38,7 @@
#include <time.h>
#include <list>
#include <memory>
#include <wx/glcanvas.h>
#include <wx/timer.h>
@ -56,12 +57,14 @@
#include <GL/glu.h>
#endif
#include <libaegisub/vfr.h>
#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<VideoDisplay*> displayList;
@ -94,27 +95,14 @@ private:
/// DOCME
AegiVideoFrame tempFrame;
/// DOCME
std::auto_ptr<VideoProvider> provider;
/// DOCME
wxString tempfile;
std::auto_ptr<SubtitlesProvider> subsProvider;
/// DOCME
VideoProvider *provider;
/// DOCME
SubtitlesProvider *subsProvider;
/// DOCME
bool keyFramesLoaded;
/// DOCME
bool overKeyFramesLoaded;
/// DOCME
wxArrayInt KeyFrames;
/// DOCME
wxArrayInt overKeyFrames;
std::vector<int> 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<int>& 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()
};

View File

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

View File

@ -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; i<KeyFrames.GetCount(); i++) {
for (unsigned int i=1; i<KeyFrames.size(); i++) {
// Is the last keyframe not this keyframe -1?
if (KeyFrames[i-1] != (int)(i-1)) {
// It's not all keyframes, go ahead
@ -304,10 +275,11 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
// If it is all keyframes, discard the keyframe info as it is useless
if (isAllKeyFrames) {
KeyFrames.Clear();
keyFramesLoaded = false;
KeyFrames.clear();
}
real_fps = (double)vi.fps_numerator / vi.fps_denominator;
// Convert to RGB32
script = env->Invoke("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

View File

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

View File

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

View File

@ -34,34 +34,14 @@
/// @ingroup video_input
///
//////////
// Headers
#ifndef AGI_PRE
#include <list>
#include <memory>
#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<VideoProvider> master;
/// DOCME
unsigned int cacheMax;
@ -80,16 +58,11 @@ private:
/// DOCME
std::list<CachedFrame> 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<int> 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<int> GetKeyFrames() const { return master->GetKeyFrames(); }
virtual wxString GetWarning() const { return master->GetWarning(); }
virtual wxString GetDecoderName() const { return master->GetDecoderName(); }
};

View File

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

View File

@ -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 <wx/colour.h>
#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<int> GetKeyFrames() const { return std::vector<int>(); };
wxString GetDecoderName() const { return L"Dummy Video Provider"; }
};

View File

@ -38,8 +38,6 @@
#ifdef WITH_FFMPEGSOURCE
///////////
// Headers
#ifndef AGI_PRE
#ifdef __WINDOWS__
#include <objbase.h>
@ -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<int> 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 */

View File

@ -34,8 +34,6 @@
/// @ingroup video_input ffms
///
///////////
// Headers
#ifdef WITH_FFMPEGSOURCE
#ifndef AGI_PRE
#include <vector>
@ -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<int> TimecodesVector; /// list of timestamps
FrameRate Timecodes; /// vfr object
std::vector<int> 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<int> 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 */

View File

@ -34,9 +34,6 @@
/// @ingroup video_input
///
///////////
// Headers
#include "config.h"
#include <libaegisub/log.h>
@ -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

View File

@ -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<int> 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 */

View File

@ -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<int> keyframes;
/// DOCME
wxArrayInt keyframes; // list of keyframes
/// DOCME
std::vector<int> qt_timestamps; // qt timestamps (used for seeking)
/// qt timestamps (used for seeking)
std::vector<int> 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<int> 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<int> 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 */

View File

@ -309,6 +309,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& 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);
}

View File

@ -34,8 +34,6 @@
/// @ingroup video_input
///
#include "include/aegisub/video_provider.h"
#ifndef AGI_PRE
#include <stdio.h>
@ -46,16 +44,12 @@
#include <wx/log.h>
#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<int64_t> 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<int> GetKeyFrames() const { return std::vector<int>(); };
wxString GetDecoderName() const { return L"YU4MPEG"; };
bool WantsCaching() const { return true; };
};

View File

@ -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<int> 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<int> 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<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int keys = KeyFrames.size();
for (int i=0;i<keys;i++) {
curX = GetXAtValue(KeyFrames[i]);
dc.DrawLine(curX,2,curX,8);

View File

@ -57,7 +57,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_provider_manager.h"

View File

@ -41,7 +41,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 "visual_tool_drag.h"
@ -290,7 +289,7 @@ bool VisualToolDrag::InitializeDrag(feature_iterator feature) {
// Set time of clicked feature to the current frame and shift all other
// selected features by the same amount
if (feature->type != 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) {