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" RelativePath="..\..\src\vector2d.h"
> >
</File> </File>
<File
RelativePath="..\..\src\vfr.cpp"
>
</File>
<File
RelativePath="..\..\src\vfr.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Dialogs" Name="Dialogs"

View File

@ -181,7 +181,7 @@ Framerate::Framerate(std::vector<int> const& timecodes)
: timecodes(timecodes) : timecodes(timecodes)
{ {
validate_timecodes(timecodes); validate_timecodes(timecodes);
fps = timecodes.size() / (timecodes.back() / 1000.); fps = (timecodes.size() - 1) * 1000. / (timecodes.back() - timecodes.front());
last = timecodes.back(); last = timecodes.back();
} }
@ -202,10 +202,6 @@ Framerate &Framerate::operator=(double fps) {
return *this = Framerate(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.) { Framerate::Framerate(std::string const& filename) : fps(0.) {
using namespace std; using namespace std;
auto_ptr<ifstream> file(agi::io::Open(filename)); 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") { if (line == "# timecode format v2") {
copy(line_iterator<int>(*file, encoding), line_iterator<int>(), back_inserter(timecodes)); copy(line_iterator<int>(*file, encoding), line_iterator<int>(), back_inserter(timecodes));
validate_timecodes(timecodes); validate_timecodes(timecodes);
fps = timecodes.size() / (timecodes.back() / 1000.); fps = (timecodes.size() - 1) * 1000. / (timecodes.back() - timecodes.front());
last = timecodes.back();
return; return;
} }
if (line == "# timecode format v1" || line.substr(0, 7) == "Assume ") { if (line == "# timecode format v1" || line.substr(0, 7) == "Assume ") {

View File

@ -132,10 +132,6 @@ public:
bool IsVFR() const {return !timecodes.empty(); } bool IsVFR() const {return !timecodes.empty(); }
bool IsLoaded() const { return !timecodes.empty() || fps; }; bool IsLoaded() const { return !timecodes.empty() || fps; };
double FPS() const { return 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 \ variable_data.cpp \
vector2d.cpp \ vector2d.cpp \
version.cpp \ version.cpp \
vfr.cpp \
video_box.cpp \ video_box.cpp \
video_context.cpp \ video_context.cpp \
video_display.cpp \ video_display.cpp \

View File

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

View File

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

View File

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

View File

@ -65,7 +65,6 @@
#include "subs_grid.h" #include "subs_grid.h"
#include "timeedit_ctrl.h" #include "timeedit_ctrl.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
#ifdef __WXMAC__ #ifdef __WXMAC__
@ -295,7 +294,7 @@ void AudioDisplay::DoUpdateImage() {
if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool()) { if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool()) {
if (VideoContext::Get()->IsLoaded()) { if (VideoContext::Get()->IsLoaded()) {
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Play Cursor")->GetColour()))); 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); dc.DrawLine(x,0,x,h);
} }
} }
@ -477,19 +476,19 @@ void AudioDisplay::DrawInactiveLines(wxDC &dc) {
/// @brief Draw keyframe markers /// @brief Draw keyframe markers
/// @param dc The DC to draw to. /// @param dc The DC to draw to.
void AudioDisplay::DrawKeyframes(wxDC &dc) { void AudioDisplay::DrawKeyframes(wxDC &dc) {
wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int nKeys = (int)KeyFrames.Count(); int nKeys = (int)KeyFrames.size();
dc.SetPen(wxPen(wxColour(255,0,255),1)); dc.SetPen(wxPen(wxColour(255,0,255),1));
// Get min and max frames to care about // Get min and max frames to care about
int minFrame = VFR_Output.GetFrameAtTime(GetMSAtX(0),true); int minFrame = VideoContext::Get()->FrameAtTime(GetMSAtX(0),agi::vfr::START);
int maxFrame = VFR_Output.GetFrameAtTime(GetMSAtX(w),true); int maxFrame = VideoContext::Get()->FrameAtTime(GetMSAtX(w),agi::vfr::END);
// Scan list // Scan list
for (int i=0;i<nKeys;i++) { for (int i=0;i<nKeys;i++) {
int cur = KeyFrames[i]; int cur = KeyFrames[i];
if (cur >= minFrame && cur <= maxFrame) { 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); dc.DrawLine(x,0,x,h);
} }
else if (cur > maxFrame) break; else if (cur > maxFrame) break;
@ -1469,7 +1468,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
if (middleClick) { if (middleClick) {
SetFocus(); SetFocus();
if (VideoContext::Get()->IsLoaded()) { 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 (shiftHeld) snapKey = !snapKey;
if (snapKey && VideoContext::Get()->KeyFramesLoaded() && OPT_GET("Audio/Display/Draw/Keyframes")->GetBool()) { if (snapKey && VideoContext::Get()->KeyFramesLoaded() && OPT_GET("Audio/Display/Draw/Keyframes")->GetBool()) {
int64_t keyMS; int64_t keyMS;
wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames(); std::vector<int> keyFrames = VideoContext::Get()->GetKeyFrames();
int frame; int frame;
for (unsigned int i=0;i<keyFrames.Count();i++) { for (unsigned int i=0;i<keyFrames.size();i++) {
frame = keyFrames[i]; frame = keyFrames[i];
if (!start) frame--; if (!start) frame--;
if (frame < 0) frame = 0; 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 (start) keyX++;
if (GetXAtMS(keyMS) >= 0 && GetXAtMS(keyMS) < w) boundaries.Add(keyMS); if (GetXAtMS(keyMS) >= 0 && GetXAtMS(keyMS) < w) boundaries.Add(keyMS);
} }

View File

@ -34,12 +34,8 @@
/// @ingroup audio_ui /// @ingroup audio_ui
/// ///
#pragma once #pragma once
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <stdint.h> #include <stdint.h>
@ -52,9 +48,6 @@
#include "audio_provider_manager.h" #include "audio_provider_manager.h"
#include "audio_renderer_spectrum.h" #include "audio_renderer_spectrum.h"
//////////////
// Prototypes
class AssDialogue; class AssDialogue;
class StreamAudioProvider; class StreamAudioProvider;
class SubtitlesGrid; class SubtitlesGrid;
@ -63,8 +56,6 @@ class AudioKaraoke;
class VideoProvider; class VideoProvider;
class FrameMain; class FrameMain;
/// DOCME /// DOCME
/// @class AudioDisplay /// @class AudioDisplay
/// @brief DOCME /// @brief DOCME
@ -83,11 +74,9 @@ private:
/// DOCME /// DOCME
AssDialogue *dialogue; AssDialogue *dialogue;
/// DOCME /// DOCME
AudioSpectrum *spectrumRenderer; AudioSpectrum *spectrumRenderer;
/// DOCME /// DOCME
wxBitmap *origImage; wxBitmap *origImage;
@ -127,14 +116,12 @@ private:
/// DOCME /// DOCME
bool playingToEnd; bool playingToEnd;
/// DOCME /// DOCME
bool needImageUpdate; bool needImageUpdate;
/// DOCME /// DOCME
bool needImageUpdateWeak; bool needImageUpdateWeak;
/// DOCME /// DOCME
bool hasSel; bool hasSel;
@ -186,14 +173,12 @@ private:
/// DOCME /// DOCME
int holdSyl; int holdSyl;
/// DOCME /// DOCME
int *peak; int *peak;
/// DOCME /// DOCME
int *min; int *min;
/// DOCME /// DOCME
int scrubTime; int scrubTime;
@ -239,7 +224,6 @@ public:
/// DOCME /// DOCME
AudioPlayer *player; AudioPlayer *player;
/// DOCME /// DOCME
bool NeedCommit; bool NeedCommit;
@ -308,11 +292,8 @@ public:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
/////// ///////
// IDs // IDs
enum { enum {
/// DOCME
Audio_Update_Timer = 1700 Audio_Update_Timer = 1700
}; };

View File

@ -64,7 +64,6 @@
#include "options.h" #include "options.h"
#include "standard_paths.h" #include "standard_paths.h"
#include "text_file_reader.h" #include "text_file_reader.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
// This must be below the headers above. // This must be below the headers above.
@ -504,8 +503,8 @@ namespace Automation4 {
{ {
int ms = (int)lua_tonumber(L, -1); int ms = (int)lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
if (VFR_Output.IsLoaded()) { if (VideoContext::Get()->TimecodesLoaded()) {
lua_pushnumber(L, VFR_Output.GetFrameAtTime(ms, true)); lua_pushnumber(L, VideoContext::Get()->FrameAtTime(ms, agi::vfr::START));
return 1; return 1;
} else { } else {
lua_pushnil(L); lua_pushnil(L);
@ -522,8 +521,8 @@ namespace Automation4 {
{ {
int frame = (int)lua_tonumber(L, -1); int frame = (int)lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
if (VFR_Output.IsLoaded()) { if (VideoContext::Get()->TimecodesLoaded()) {
lua_pushnumber(L, VFR_Output.GetTimeAtFrame(frame, true)); lua_pushnumber(L, VideoContext::Get()->TimeAtFrame(frame, agi::vfr::START));
return 1; return 1;
} else { } else {
lua_pushnil(L); lua_pushnil(L);

View File

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

View File

@ -34,9 +34,6 @@
/// @ingroup main_ui /// @ingroup main_ui
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -56,7 +53,6 @@
#include "options.h" #include "options.h"
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_slider.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) BaseGrid::BaseGrid(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
: wxWindow(parent, id, pos, size, style, name) : wxWindow(parent, id, pos, size, style, name)
, context(VideoContext::Get())
{ {
// Misc variables // Misc variables
lastRow = -1; 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"),curRow+1));
strings.Add(wxString::Format(_T("%i"),curDiag->Layer)); strings.Add(wxString::Format(_T("%i"),curDiag->Layer));
if (byFrame) { if (byFrame) {
strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true))); strings.Add(wxString::Format(_T("%i"),context->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START)));
strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),false))); strings.Add(wxString::Format(_T("%i"),context->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END)));
} }
else { else {
strings.Add(curDiag->Start.GetASSFormated()); strings.Add(curDiag->Start.GetASSFormated());
@ -787,7 +784,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
// Normal click // Normal click
if ((click || dclick) && !shift && !ctrl && !alt) { if ((click || dclick) && !shift && !ctrl && !alt) {
SetActiveLine(dlg); SetActiveLine(dlg);
if (dclick) VideoContext::Get()->JumpToTime(dlg->Start.GetMS()); if (dclick) context->JumpToTime(dlg->Start.GetMS());
SelectRow(row,false); SelectRow(row,false);
parentFrame->UpdateToolbar(); parentFrame->UpdateToolbar();
lastRow = row; lastRow = row;
@ -964,9 +961,9 @@ void BaseGrid::SetColumnWidths() {
// Times // Times
if (byFrame) { 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; 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; if (tmp > maxEnd) maxEnd = tmp;
} }
} }
@ -1053,8 +1050,8 @@ int BaseGrid::GetDialogueIndex(AssDialogue *diag) const {
bool BaseGrid::IsDisplayed(AssDialogue *line) { bool BaseGrid::IsDisplayed(AssDialogue *line) {
VideoContext* con = VideoContext::Get(); VideoContext* con = VideoContext::Get();
if (!con->IsLoaded()) return false; if (!con->IsLoaded()) return false;
int f1 = VFR_Output.GetFrameAtTime(line->Start.GetMS(),true); int f1 = con->FrameAtTime(line->Start.GetMS(),agi::vfr::START);
int f2 = VFR_Output.GetFrameAtTime(line->End.GetMS(),false); int f2 = con->FrameAtTime(line->End.GetMS(),agi::vfr::END);
if (f1 <= con->GetFrameN() && f2 >= con->GetFrameN()) return true; if (f1 <= con->GetFrameN() && f2 >= con->GetFrameN()) return true;
return false; return false;
} }
@ -1106,7 +1103,7 @@ void BaseGrid::OnKeyPress(wxKeyEvent &event) {
// Left/right, forward to seek bar if video is loaded // Left/right, forward to seek bar if video is loaded
if (key == WXK_LEFT || key == WXK_RIGHT) { if (key == WXK_LEFT || key == WXK_RIGHT) {
if (VideoContext::Get()->IsLoaded()) { if (context->IsLoaded()) {
parentFrame->videoBox->videoSlider->SetFocus(); parentFrame->videoBox->videoSlider->SetFocus();
parentFrame->videoBox->videoSlider->GetEventHandler()->ProcessEvent(event); parentFrame->videoBox->videoSlider->GetEventHandler()->ProcessEvent(event);
return; return;
@ -1197,8 +1194,8 @@ void BaseGrid::OnKeyPress(wxKeyEvent &event) {
} }
// Other events, send to audio display // Other events, send to audio display
if (VideoContext::Get()->audio->loaded) { if (context->audio->loaded) {
VideoContext::Get()->audio->GetEventHandler()->ProcessEvent(event); context->audio->GetEventHandler()->ProcessEvent(event);
} }
else event.Skip(); else event.Skip();
} }

View File

@ -37,8 +37,6 @@
#pragma once #pragma once
////////////
// Includes
#ifndef AGI_PRE #ifndef AGI_PRE
#include <list> #include <list>
#include <vector> #include <vector>
@ -49,13 +47,11 @@
#include "selection_controller.h" #include "selection_controller.h"
//////////////
// Prototypes
class AssEntry; class AssEntry;
class AssDialogue; class AssDialogue;
class SubsEditBox; class SubsEditBox;
class FrameMain; class FrameMain;
class VideoContext;
/// DOCME /// DOCME
typedef std::list<AssEntry*>::iterator entryIter; typedef std::list<AssEntry*>::iterator entryIter;
@ -71,8 +67,6 @@ typedef SelectionListener<AssDialogue> SubtitleSelectionListener;
/// ///
/// DOCME /// DOCME
class BaseGrid : public wxWindow, public BaseSelectionController<AssDialogue> { class BaseGrid : public wxWindow, public BaseSelectionController<AssDialogue> {
private:
/// DOCME /// DOCME
int lineHeight; int lineHeight;
@ -120,11 +114,12 @@ protected:
/// DOCME /// DOCME
FrameMain *parentFrame; FrameMain *parentFrame;
VideoContext *context;
/// DOCME /// DOCME
static const int columns = 10; static const int columns = 10;
bool showCol[columns]; bool showCol[columns];
/// @brief DOCME /// @brief DOCME
/// @param alternate /// @param alternate
/// ///

View File

@ -34,9 +34,6 @@
/// @ingroup secondary_ui /// @ingroup secondary_ui
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -50,36 +47,26 @@
#include "dialog_jumpto.h" #include "dialog_jumpto.h"
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
/// Event IDs
///////
// IDs
enum { enum {
/// DOCME
TEXT_JUMP_TIME = 1100, TEXT_JUMP_TIME = 1100,
/// DOCME
TEXT_JUMP_FRAME TEXT_JUMP_FRAME
}; };
/// @brief Constructor /// @brief Constructor
/// @param parent /// @param parent
/// ///
DialogJumpTo::DialogJumpTo (wxWindow *parent) DialogJumpTo::DialogJumpTo (wxWindow *parent)
: wxDialog(parent, -1, _("Jump to"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS , _T("JumpTo")) : wxDialog(parent, -1, _("Jump to"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS , _T("JumpTo"))
{ {
// Set icon
SetIcon(BitmapToIcon(GETIMAGE(jumpto_button_24))); SetIcon(BitmapToIcon(GETIMAGE(jumpto_button_24)));
// Set initial values // Set initial values
ready = false; ready = false;
jumpframe = VideoContext::Get()->GetFrameN(); 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); wxString maxLength = wxString::Format(_T("%i"),VideoContext::Get()->GetLength()-1);
// Times // Times
@ -117,9 +104,6 @@ DialogJumpTo::DialogJumpTo (wxWindow *parent)
ready = true; ready = true;
} }
///////////////
// Event table
BEGIN_EVENT_TABLE(DialogJumpTo, wxDialog) BEGIN_EVENT_TABLE(DialogJumpTo, wxDialog)
EVT_TEXT_ENTER(TEXT_JUMP_FRAME,DialogJumpTo::OnKey) EVT_TEXT_ENTER(TEXT_JUMP_FRAME,DialogJumpTo::OnKey)
EVT_TEXT_ENTER(TEXT_JUMP_TIME,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) EVT_TEXT(TEXT_JUMP_FRAME, DialogJumpTo::OnEditFrame)
END_EVENT_TABLE() END_EVENT_TABLE()
void DialogJumpTo::OnCloseButton (wxCommandEvent &) { OnClose(false); }
void DialogJumpTo::OnOK (wxCommandEvent &) { OnClose(true); }
/// @brief Close
/// @param event
///
void DialogJumpTo::OnCloseButton (wxCommandEvent &event) { OnClose(false); }
/// @brief DOCME
/// @param event
///
void DialogJumpTo::OnOK (wxCommandEvent &event) { OnClose(true); }
/// @brief On Key pressed /// @brief On Key pressed
/// @param event void DialogJumpTo::OnKey(wxCommandEvent &) {
///
void DialogJumpTo::OnKey(wxCommandEvent &event) {
EndModal(0); EndModal(0);
if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1; if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1;
VideoContext::Get()->JumpToFrame(jumpframe); VideoContext::Get()->JumpToFrame(jumpframe);
} }
/// @brief On OK button pressed /// @brief On OK button pressed
/// @param ok /// @param ok
///
void DialogJumpTo::OnClose(bool ok) { void DialogJumpTo::OnClose(bool ok) {
EndModal(0); EndModal(0);
if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1; if (jumpframe > VideoContext::Get()->GetLength()-1) jumpframe = VideoContext::Get()->GetLength()-1;
if (ok) VideoContext::Get()->JumpToFrame(jumpframe); if (ok) VideoContext::Get()->JumpToFrame(jumpframe);
} }
/// @brief Time editbox changed /// @brief Time editbox changed
/// @param event /// @param event
/// ///
@ -173,10 +139,10 @@ void DialogJumpTo::OnEditTime (wxCommandEvent &event) {
ready = false; ready = false;
// Update frame // Update frame
long newframe = VFR_Output.GetFrameAtTime(JumpTime->time.GetMS()); long newframe = VideoContext::Get()->FrameAtTime(JumpTime->time.GetMS());
if (jumpframe != newframe) { if (jumpframe != newframe) {
jumpframe = newframe; jumpframe = newframe;
JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe)); JumpFrame->ChangeValue(wxString::Format(_T("%i"),jumpframe));
} }
ready = true; ready = true;
@ -184,8 +150,6 @@ void DialogJumpTo::OnEditTime (wxCommandEvent &event) {
else event.Skip(); else event.Skip();
} }
/// @brief Frame editbox changed /// @brief Frame editbox changed
/// @param event /// @param event
/// ///
@ -199,7 +163,7 @@ void DialogJumpTo::OnEditFrame (wxCommandEvent &event) {
JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe)); JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe));
// Update time // Update time
int newtime = VFR_Output.GetTimeAtFrame(jumpframe,true,true); int newtime = VideoContext::Get()->TimeAtFrame(jumpframe);
if (jumptime.GetMS() != newtime) { if (jumptime.GetMS() != newtime) {
jumptime.SetMS(newtime); jumptime.SetMS(newtime);
JumpTime->ChangeValue(jumptime.GetASSFormated()); JumpTime->ChangeValue(jumptime.GetASSFormated());
@ -209,5 +173,3 @@ void DialogJumpTo::OnEditFrame (wxCommandEvent &event) {
} }
else event.Skip(); else event.Skip();
} }

View File

@ -61,10 +61,9 @@
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "vfr.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
/// @brief Constructor /// @brief Constructor
/// @param parent /// @param parent
/// @param _grid /// @param _grid
@ -92,7 +91,7 @@ DialogShiftTimes::DialogShiftTimes (wxWindow *parent,SubtitlesGrid *_grid)
ShiftTime->SetToolTip(_("Enter time in h:mm:ss.cs notation")); ShiftTime->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
RadioTime->SetToolTip(_("Shift by time")); RadioTime->SetToolTip(_("Shift by time"));
ShiftFrame->Disable(); ShiftFrame->Disable();
if (!VFR_Output.IsLoaded()) RadioFrames->Disable(); if (!VideoContext::Get()->TimecodesLoaded()) RadioFrames->Disable();
else { else {
ShiftFrame->SetToolTip(_("Enter number of frames to shift by")); ShiftFrame->SetToolTip(_("Enter number of frames to shift by"));
RadioFrames->SetToolTip(_("Shift by frames")); RadioFrames->SetToolTip(_("Shift by frames"));

View File

@ -34,8 +34,6 @@
/// @ingroup tools_ui /// @ingroup tools_ui
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
@ -49,11 +47,20 @@
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "validators.h" #include "validators.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.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 /// @brief Constructor
/// @param parent /// @param parent
@ -62,7 +69,6 @@
DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_grid) DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_grid)
: wxDialog(parent,-1,_("Timing Post-Processor"),wxDefaultPosition,wxSize(400,250),wxDEFAULT_DIALOG_STYLE) : wxDialog(parent,-1,_("Timing Post-Processor"),wxDefaultPosition,wxSize(400,250),wxDEFAULT_DIALOG_STYLE)
{ {
// Set icon
SetIcon(BitmapToIcon(GETIMAGE(timing_processor_toolbutton_24))); SetIcon(BitmapToIcon(GETIMAGE(timing_processor_toolbutton_24)));
// Set variables // 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()); thresEndAfter = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key End After")->GetInt());
adjsThresTime = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt()); adjsThresTime = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt());
// Styles box // Styles box
wxSizer *LeftSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Apply to styles")); wxSizer *LeftSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Apply to styles"));
wxArrayString styles = grid->ass->GetStyles(); wxArrayString styles = grid->ass->GetStyles();
@ -201,12 +206,9 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr
CenterOnParent(); CenterOnParent();
// Update
UpdateControls(); UpdateControls();
} }
/// @brief Update controls /// @brief Update controls
/// ///
void DialogTimingProcessor::UpdateControls() { void DialogTimingProcessor::UpdateControls() {
@ -237,9 +239,6 @@ void DialogTimingProcessor::UpdateControls() {
ApplyButton->Enable(checked && (hasLeadIn->IsChecked() | hasLeadOut->IsChecked() | keysEnable->IsChecked() | adjsEnable->IsChecked())); ApplyButton->Enable(checked && (hasLeadIn->IsChecked() | hasLeadOut->IsChecked() | keysEnable->IsChecked() | adjsEnable->IsChecked()));
} }
///////////////
// Event table
BEGIN_EVENT_TABLE(DialogTimingProcessor,wxDialog) BEGIN_EVENT_TABLE(DialogTimingProcessor,wxDialog)
EVT_CHECKBOX(CHECK_ENABLE_LEADIN,DialogTimingProcessor::OnCheckBox) EVT_CHECKBOX(CHECK_ENABLE_LEADIN,DialogTimingProcessor::OnCheckBox)
EVT_CHECKBOX(CHECK_ENABLE_LEADOUT,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) EVT_BUTTON(BUTTON_SELECT_NONE,DialogTimingProcessor::OnSelectNone)
END_EVENT_TABLE() END_EVENT_TABLE()
void DialogTimingProcessor::OnCheckBox(wxCommandEvent &) {
/// @brief Checkbox clicked
/// @param event
///
void DialogTimingProcessor::OnCheckBox(wxCommandEvent &event) {
UpdateControls(); UpdateControls();
} }
void DialogTimingProcessor::OnSelectAll(wxCommandEvent &) {
/// @brief Select all styles
/// @param event
///
void DialogTimingProcessor::OnSelectAll(wxCommandEvent &event) {
size_t len = StyleList->GetCount(); size_t len = StyleList->GetCount();
for (size_t i=0;i<len;i++) { for (size_t i=0;i<len;i++) {
StyleList->Check(i); StyleList->Check(i);
@ -273,12 +262,7 @@ void DialogTimingProcessor::OnSelectAll(wxCommandEvent &event) {
UpdateControls(); UpdateControls();
} }
void DialogTimingProcessor::OnSelectNone(wxCommandEvent &) {
/// @brief Unselect all styles
/// @param event
///
void DialogTimingProcessor::OnSelectNone(wxCommandEvent &event) {
size_t len = StyleList->GetCount(); size_t len = StyleList->GetCount();
for (size_t i=0;i<len;i++) { for (size_t i=0;i<len;i++) {
StyleList->Check(i,false); StyleList->Check(i,false);
@ -286,12 +270,7 @@ void DialogTimingProcessor::OnSelectNone(wxCommandEvent &event) {
UpdateControls(); UpdateControls();
} }
void DialogTimingProcessor::OnApply(wxCommandEvent &) {
/// @brief Apply button pressed
/// @param event
///
void DialogTimingProcessor::OnApply(wxCommandEvent &event) {
// Save settings // Save settings
long temp = 0; long temp = 0;
leadIn->GetValue().ToLong(&temp); leadIn->GetValue().ToLong(&temp);
@ -330,26 +309,16 @@ void DialogTimingProcessor::OnApply(wxCommandEvent &event) {
} }
} }
// Process
if (valid) 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); 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); EndModal(0);
} }
/// @brief Get closest keyframe
/// @param frame
/// @return
///
int DialogTimingProcessor::GetClosestKeyFrame(int frame) { int DialogTimingProcessor::GetClosestKeyFrame(int frame) {
// Linear dumb search, not very efficient, but it doesn't really matter // Linear dumb search, not very efficient, but it doesn't really matter
int closest = 0; int closest = 0;
size_t n = KeyFrames.Count(); size_t n = KeyFrames.size();
for (size_t i=0;i<n;i++) { for (size_t i=0;i<n;i++) {
if (abs(KeyFrames[i]-frame) < abs(closest-frame)) { if (abs(KeyFrames[i]-frame) < abs(closest-frame)) {
closest = KeyFrames[i]; closest = KeyFrames[i];
@ -358,8 +327,6 @@ int DialogTimingProcessor::GetClosestKeyFrame(int frame) {
return closest; return closest;
} }
/// @brief Check if style is listed /// @brief Check if style is listed
/// @param styleName /// @param styleName
/// @return /// @return
@ -372,8 +339,6 @@ bool DialogTimingProcessor::StyleOK(wxString styleName) {
return false; return false;
} }
/// @brief Sort dialogues /// @brief Sort dialogues
/// ///
void DialogTimingProcessor::SortDialogues() { void DialogTimingProcessor::SortDialogues() {
@ -400,8 +365,6 @@ void DialogTimingProcessor::SortDialogues() {
} }
} }
/// @brief Gets sorted dialogue /// @brief Gets sorted dialogue
/// @param n /// @param n
/// @return /// @return
@ -415,12 +378,9 @@ AssDialogue *DialogTimingProcessor::GetSortedDialogue(int n) {
} }
} }
/// @brief Actually process subtitles /// @brief Actually process subtitles
/// ///
void DialogTimingProcessor::Process() { void DialogTimingProcessor::Process() {
// Sort rows
SortDialogues(); SortDialogues();
int rows = Sorted.size(); int rows = Sorted.size();
@ -539,8 +499,9 @@ void DialogTimingProcessor::Process() {
// Keyframe snapping // Keyframe snapping
if (keysEnable->IsChecked()) { if (keysEnable->IsChecked()) {
// Get keyframes // Get keyframes
KeyFrames = VideoContext::Get()->GetKeyFrames(); VideoContext *con = VideoContext::Get();
KeyFrames.Add(VideoContext::Get()->GetLength()-1); KeyFrames = con->GetKeyFrames();
KeyFrames.push_back(con->GetLength()-1);
// Variables // Variables
int startF,endF; int startF,endF;
@ -563,19 +524,19 @@ void DialogTimingProcessor::Process() {
cur = GetSortedDialogue(i); cur = GetSortedDialogue(i);
// Get start/end frames // Get start/end frames
startF = VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true); startF = con->FrameAtTime(cur->Start.GetMS(),agi::vfr::START);
endF = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false); endF = con->FrameAtTime(cur->End.GetMS(),agi::vfr::END);
// Get closest for start // Get closest for start
closest = GetClosestKeyFrame(startF); closest = GetClosestKeyFrame(startF);
if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) { 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 // Get closest for end
closest = GetClosestKeyFrame(endF)-1; closest = GetClosestKeyFrame(endF)-1;
if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) { 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->ass->FlagAsModified(_("timing processor"));
grid->CommitChanges(); grid->CommitChanges();
} }

View File

@ -34,11 +34,6 @@
/// @ingroup tools_ui /// @ingroup tools_ui
/// ///
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <vector> #include <vector>
@ -51,33 +46,24 @@
#include <wx/textctrl.h> #include <wx/textctrl.h>
#endif #endif
//////////////
// Prototypes
class SubtitlesGrid; class SubtitlesGrid;
class AssDialogue; class AssDialogue;
/// DOCME /// DOCME
/// @class DialogTimingProcessor /// @class DialogTimingProcessor
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class DialogTimingProcessor : public wxDialog { class DialogTimingProcessor : public wxDialog {
private:
/// DOCME /// DOCME
SubtitlesGrid *grid; SubtitlesGrid *grid;
/// DOCME /// DOCME
wxStaticBoxSizer *KeyframesSizer; wxStaticBoxSizer *KeyframesSizer;
/// DOCME /// DOCME
wxCheckBox *onlySelection; wxCheckBox *onlySelection;
/// DOCME /// DOCME
wxTextCtrl *leadIn; wxTextCtrl *leadIn;
@ -90,7 +76,6 @@ private:
/// DOCME /// DOCME
wxCheckBox *hasLeadOut; wxCheckBox *hasLeadOut;
/// DOCME /// DOCME
wxCheckBox *keysEnable; wxCheckBox *keysEnable;
@ -106,7 +91,6 @@ private:
/// DOCME /// DOCME
wxTextCtrl *keysEndAfter; wxTextCtrl *keysEndAfter;
/// DOCME /// DOCME
wxCheckBox *adjsEnable; wxCheckBox *adjsEnable;
@ -116,7 +100,6 @@ private:
/// DOCME /// DOCME
wxSlider *adjacentBias; wxSlider *adjacentBias;
/// DOCME /// DOCME
wxCheckListBox *StyleList; wxCheckListBox *StyleList;
@ -138,9 +121,8 @@ private:
/// DOCME /// DOCME
wxString leadInTime,leadOutTime,thresStartBefore,thresStartAfter,thresEndBefore,thresEndAfter,adjsThresTime; wxString leadInTime,leadOutTime,thresStartBefore,thresStartAfter,thresEndBefore,thresEndAfter,adjsThresTime;
/// DOCME /// DOCME
wxArrayInt KeyFrames; std::vector<int> KeyFrames;
void OnCheckBox(wxCommandEvent &event); void OnCheckBox(wxCommandEvent &event);
void OnSelectAll(wxCommandEvent &event); void OnSelectAll(wxCommandEvent &event);
@ -152,7 +134,6 @@ private:
int GetClosestKeyFrame(int frame); int GetClosestKeyFrame(int frame);
bool StyleOK(wxString styleName); bool StyleOK(wxString styleName);
/// DOCME /// DOCME
std::vector<AssDialogue*> Sorted; std::vector<AssDialogue*> Sorted;
AssDialogue *GetSortedDialogue(int n); AssDialogue *GetSortedDialogue(int n);
@ -163,30 +144,3 @@ public:
DECLARE_EVENT_TABLE() 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 width = vprovider->GetWidth();
int height = vprovider->GetHeight(); int height = vprovider->GetHeight();
int framecount = vprovider->GetFrameCount(); 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 *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); 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 "ass_override.h"
#include "export_framerate.h" #include "export_framerate.h"
#include "utils.h" #include "utils.h"
#include "video_context.h"
/// DOCME /// DOCME
/// @class LineData /// @class LineData
@ -93,11 +94,13 @@ void AssTransformFramerateFilter::ProcessSubs(AssFile *subs, wxWindow *export_di
wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) { wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) {
wxWindow *base = new wxPanel(parent, -1); wxWindow *base = new wxPanel(parent, -1);
LoadSettings(true);
// Input sizer // Input sizer
wxSizer *InputSizer = new wxBoxSizer(wxHORIZONTAL); wxSizer *InputSizer = new wxBoxSizer(wxHORIZONTAL);
wxString initialInput; wxString initialInput;
wxButton *FromVideo = new wxButton(base,Get_Input_From_Video,_("From Video")); 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 { else {
initialInput = _T("23.976"); initialInput = _T("23.976");
FromVideo->Enable(false); FromVideo->Enable(false);
@ -119,7 +122,7 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) {
// Output bottom line // Output bottom line
RadioOutputCFR = new wxRadioButton(base,-1,_("Constant: ")); RadioOutputCFR = new wxRadioButton(base,-1,_("Constant: "));
wxString initialOutput = initialInput; wxString initialOutput = initialInput;
if (VFR_Output.GetFrameRateType() != VFR) { if (!Output->IsVFR()) {
RadioOutputVFR->Enable(false); RadioOutputVFR->Enable(false);
RadioOutputCFR->SetValue(true); RadioOutputCFR->SetValue(true);
} }
@ -150,20 +153,20 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) {
void AssTransformFramerateFilter::LoadSettings(bool IsDefault) { void AssTransformFramerateFilter::LoadSettings(bool IsDefault) {
if (IsDefault) { if (IsDefault) {
Input = &VFR_Input; Input = &VideoContext::Get()->VFR_Input;
Output = &VFR_Output; Output = &VideoContext::Get()->VFR_Output;
} }
else { else {
double temp; double temp;
InputFramerate->GetValue().ToDouble(&temp); InputFramerate->GetValue().ToDouble(&temp);
t1.SetCFR(temp); t1 = temp;
Input = &t1; Input = &t1;
if (RadioOutputCFR->GetValue()) { if (RadioOutputCFR->GetValue()) {
OutputFramerate->GetValue().ToDouble(&temp); OutputFramerate->GetValue().ToDouble(&temp);
t2.SetCFR(temp); t2 = temp;
Output = &t2; Output = &t2;
} }
else Output = &VFR_Output; else Output = &VideoContext::Get()->VFR_Output;
if (Reverse->IsChecked()) { if (Reverse->IsChecked()) {
std::swap(Input, Output); std::swap(Input, Output);
@ -215,7 +218,7 @@ void AssTransformFramerateFilter::TransformTimeTags (wxString name,int n,AssOver
} }
void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { 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++) { for (entryIter cur=subs->Line.begin();cur!=subs->Line.end();cur++) {
AssDialogue *curDialogue = dynamic_cast<AssDialogue*>(*cur); AssDialogue *curDialogue = dynamic_cast<AssDialogue*>(*cur);
@ -225,7 +228,7 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) {
data.newK = 0; data.newK = 0;
data.oldK = 0; data.oldK = 0;
data.newStart = trunc_cs(ConvertTime(curDialogue->Start.GetMS())); 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 // Process stuff
curDialogue->ParseASSTags(); curDialogue->ParseASSTags();
@ -239,16 +242,18 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) {
} }
int AssTransformFramerateFilter::ConvertTime(int time) { int AssTransformFramerateFilter::ConvertTime(int time) {
int frame = Output->GetFrameAtTime(time, false); int frame = Output->FrameAtTime(time);
int frameStart = Output->GetTimeAtFrame(frame, false, true); int frameStart = Output->TimeAtFrame(frame);
int frameEnd = Output->GetTimeAtFrame(frame + 1, false, true); int frameEnd = Output->TimeAtFrame(frame + 1);
int frameDur = frameEnd - frameStart; int frameDur = frameEnd - frameStart;
double dist = double(time - frameStart) / frameDur; double dist = double(time - frameStart) / frameDur;
int newStart = Input->GetTimeAtFrame(frame, false, true); int newStart = Input->TimeAtFrame(frame);
int newEnd = Input->GetTimeAtFrame(frame + 1, false, true); int newEnd = Input->TimeAtFrame(frame + 1);
int newDur = newEnd - newStart; int newDur = newEnd - newStart;
int dongs = Input->FrameAtTime(newStart + newDur * dist, agi::vfr::END);
return newStart + newDur * dist; return newStart + newDur * dist;
} }

View File

@ -35,7 +35,7 @@
/// ///
#include "ass_export_filter.h" #include "ass_export_filter.h"
#include "vfr.h" #include <libaegisub/vfr.h>
class AssDialogue; class AssDialogue;
class AssOverrideParameter; class AssOverrideParameter;
@ -51,10 +51,10 @@ class AssTransformFramerateFilter : public AssExportFilter {
static AssTransformFramerateFilter instance; static AssTransformFramerateFilter instance;
// Yes, these are backwards // Yes, these are backwards
FrameRate *Input; /// Destination frame rate const agi::vfr::Framerate *Input; /// Destination frame rate
FrameRate *Output; /// Source 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 *InputFramerate; /// Input frame rate text box
wxTextCtrl *OutputFramerate; /// Output frame rate text box wxTextCtrl *OutputFramerate; /// Output frame rate text box

View File

@ -34,17 +34,13 @@
/// @ingroup export /// @ingroup export
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "ass_override.h" #include "ass_override.h"
#include "export_visible_lines.h" #include "export_visible_lines.h"
#include "vfr.h" #include "video_context.h"
/// @brief Constructor /// @brief Constructor
/// ///
@ -53,11 +49,6 @@ AssLimitToVisibleFilter::AssLimitToVisibleFilter() {
frame = -1; frame = -1;
} }
/// @brief Init
/// @return
///
void AssLimitToVisibleFilter::Init() { void AssLimitToVisibleFilter::Init() {
if (initialized) return; if (initialized) return;
initialized = true; initialized = true;
@ -67,15 +58,10 @@ void AssLimitToVisibleFilter::Init() {
description = _("Limit to Visible Lines"); description = _("Limit to Visible Lines");
} }
/// @brief Process /// @brief Process
/// @param subs /// @param subs
/// @param export_dialog /// @param export_dialog
/// @return
///
void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) { void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) {
// Nothing to do
if (frame == -1) return; if (frame == -1) return;
AssDialogue *diag; AssDialogue *diag;
@ -86,8 +72,8 @@ void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog
diag = dynamic_cast<AssDialogue*>(*cur); diag = dynamic_cast<AssDialogue*>(*cur);
if (diag) { if (diag) {
// Invisible, remove frame // Invisible, remove frame
if (VFR_Output.GetFrameAtTime(diag->Start.GetMS(),true) > frame || if (VideoContext::Get()->FrameAtTime(diag->Start.GetMS(),agi::vfr::START) > frame ||
VFR_Output.GetFrameAtTime(diag->End.GetMS(),false) < frame) { VideoContext::Get()->FrameAtTime(diag->End.GetMS(),agi::vfr::END) < frame) {
delete *cur; delete *cur;
subs->Line.erase(cur); subs->Line.erase(cur);
@ -96,8 +82,6 @@ void AssLimitToVisibleFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog
} }
} }
/// @brief Set limitation time /// @brief Set limitation time
/// @param _frame /// @param _frame
/// ///
@ -105,9 +89,5 @@ void AssLimitToVisibleFilter::SetFrame(int _frame) {
instance.frame = _frame; instance.frame = _frame;
} }
/// DOCME /// DOCME
AssLimitToVisibleFilter AssLimitToVisibleFilter::instance; AssLimitToVisibleFilter AssLimitToVisibleFilter::instance;

View File

@ -79,7 +79,6 @@
#include "text_file_writer.h" #include "text_file_writer.h"
#include "utils.h" #include "utils.h"
#include "version.h" #include "version.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
@ -642,6 +641,7 @@ void FrameMain::DeInitContents() {
AssFile::StackReset(); AssFile::StackReset();
delete AssFile::top; delete AssFile::top;
HelpButton::ClearPages(); HelpButton::ClearPages();
VideoContext::Get()->audio = NULL;
} }
/// @brief Update toolbar /// @brief Update toolbar
@ -760,6 +760,8 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
// Update title bar // Update title bar
UpdateTitle(); UpdateTitle();
VideoContext::Get()->Refresh();
} }
/// @brief Save subtitles /// @brief Save subtitles
@ -949,7 +951,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
int autoLoadMode = OPT_GET("App/Auto/Load Linked Files")->GetInt(); int autoLoadMode = OPT_GET("App/Auto/Load Linked Files")->GetInt();
bool hasToLoad = false; bool hasToLoad = false;
if (curSubsAudio != audioBox->audioName || if (curSubsAudio != audioBox->audioName ||
curSubsVFR != VFR_Output.GetFilename() || curSubsVFR != VideoContext::Get()->GetTimecodesName() ||
curSubsVideo != VideoContext::Get()->videoName || curSubsVideo != VideoContext::Get()->videoName ||
curSubsKeyframes != VideoContext::Get()->GetKeyFramesName() curSubsKeyframes != VideoContext::Get()->GetKeyFramesName()
#ifdef WITH_AUTOMATION #ifdef WITH_AUTOMATION
@ -970,25 +972,18 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
} }
if (doLoad) { if (doLoad) {
// Variable frame rate
LoadVFR(curSubsVFR);
// Video // Video
if (curSubsVideo != VideoContext::Get()->videoName) { if (curSubsVideo != VideoContext::Get()->videoName) {
//if (curSubsVideo != _T("")) {
LoadVideo(curSubsVideo); LoadVideo(curSubsVideo);
if (VideoContext::Get()->IsLoaded()) { if (VideoContext::Get()->IsLoaded()) {
VideoContext::Get()->SetAspectRatio(videoAr,videoArValue); VideoContext::Get()->SetAspectRatio(videoAr,videoArValue);
videoBox->videoDisplay->SetZoom(videoZoom); videoBox->videoDisplay->SetZoom(videoZoom);
VideoContext::Get()->JumpToFrame(videoPos); VideoContext::Get()->JumpToFrame(videoPos);
} }
//}
} }
// Keyframes VideoContext::Get()->LoadTimecodes(curSubsVFR);
if (curSubsKeyframes != _T("")) { VideoContext::Get()->LoadKeyframes(curSubsKeyframes);
KeyFrameFile::Load(curSubsKeyframes);
}
// Audio // Audio
if (curSubsAudio != audioBox->audioName) { if (curSubsAudio != audioBox->audioName) {
@ -1058,7 +1053,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
subs->SetScriptInfo(_T("Video Aspect Ratio"),ar); subs->SetScriptInfo(_T("Video Aspect Ratio"),ar);
subs->SetScriptInfo(_T("Video Zoom Percent"),zoom); subs->SetScriptInfo(_T("Video Zoom Percent"),zoom);
subs->SetScriptInfo(_T("Video Position"),seekpos); 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)); subs->SetScriptInfo(_T("Keyframes File"),MakeRelativePath(VideoContext::Get()->GetKeyFramesName(),AssFile::top->filename));
// Store Automation script data // Store Automation script data
@ -1104,26 +1099,11 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
void FrameMain::LoadVideo(wxString file,bool autoload) { void FrameMain::LoadVideo(wxString file,bool autoload) {
if (blockVideoLoad) return; if (blockVideoLoad) return;
Freeze(); Freeze();
VideoContext::Get()->Stop();
try { 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); VideoContext::Get()->SetVideo(file);
} }
catch (const wchar_t *error) { catch (const wchar_t *error) {
wxString err(error); wxMessageBox(error, _T("Error opening video file"), wxOK | wxICON_ERROR, this);
wxMessageBox(err, _T("Error opening video file"), wxOK | wxICON_ERROR, this);
} }
catch (...) { catch (...) {
wxMessageBox(_T("Unknown error"), _T("Error opening video file"), wxOK | wxICON_ERROR, this); 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) { void FrameMain::LoadVFR(wxString filename) {
VideoContext::Get()->Stop(); if (filename.empty()) {
if (filename != _T("")) { VideoContext::Get()->CloseTimecodes();
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);
}
}
else { else {
VFR_Output.Unload(); VideoContext::Get()->LoadTimecodes(filename);
if (VideoContext::Get()->IsLoaded() && !VFR_Output.IsLoaded()) {
VFR_Output.SetCFR(VideoContext::Get()->GetFPS());
} }
}
SubsGrid->CommitChanges(); SubsGrid->CommitChanges();
EditBox->UpdateFrameTiming(); EditBox->UpdateFrameTiming();
} }
/// @brief Saves VFR
/// @param filename
void FrameMain::SaveVFR(wxString filename) {
VFR_Output.Save(filename);
}
/// @brief Open help /// @brief Open help
void FrameMain::OpenHelp(wxString) { void FrameMain::OpenHelp(wxString) {
HelpButton::OpenPage(_T("Main")); HelpButton::OpenPage(_T("Main"));

View File

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

View File

@ -89,7 +89,6 @@
#include "subs_grid.h" #include "subs_grid.h"
#include "toggle_bitmap.h" #include "toggle_bitmap.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.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_235,attached);
MenuBar->Enable(Menu_Video_AR_Custom,attached); MenuBar->Enable(Menu_Video_AR_Custom,attached);
MenuBar->Enable(Menu_Video_Detach,state); MenuBar->Enable(Menu_Video_Detach,state);
MenuBar->Enable(Menu_File_Save_VFR,VFR_Output.GetFrameRateType() == VFR); MenuBar->Enable(Menu_File_Save_VFR,VideoContext::Get()->TimecodesLoaded());
MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.GetFrameRateType() == VFR); MenuBar->Enable(Menu_File_Close_VFR,VideoContext::Get()->OverTimecodesLoaded());
MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded()); MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded());
MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded()); MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded());
MenuBar->Enable(Menu_Video_Details,state); MenuBar->Enable(Menu_Video_Details,state);
@ -399,7 +398,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
MenuBar->Enable(Menu_Subtitles_Insert,state); MenuBar->Enable(Menu_Subtitles_Insert,state);
state = count > 0 && continuous; state = count > 0 && continuous;
MenuBar->Enable(MENU_DUPLICATE,state); 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); MenuBar->Enable(MENU_DUPLICATE_NEXT_FRAME,state);
state = count == 2; state = count == 2;
MenuBar->Enable(MENU_SWAP,state); MenuBar->Enable(MENU_SWAP,state);
@ -540,7 +539,7 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
/// @param event /// @param event
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) { void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
int number = event.GetId()-Menu_Keyframes_Recent; 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(); videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update(); audioBox->audioDisplay->Update();
Refresh(); Refresh();
@ -789,7 +788,7 @@ void FrameMain::OnSaveVFR(wxCommandEvent &) {
+ _("All Files") + _T(" (*.*)|*.*"); + _("All Files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (!filename.empty()) { if (!filename.empty()) {
SaveVFR(filename); VideoContext::Get()->SaveTimecodes(filename);
OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename));
} }
} }
@ -797,19 +796,26 @@ void FrameMain::OnSaveVFR(wxCommandEvent &) {
/// @brief Close VFR tags /// @brief Close VFR tags
void FrameMain::OnCloseVFR(wxCommandEvent &) { void FrameMain::OnCloseVFR(wxCommandEvent &) {
LoadVFR(_T("")); LoadVFR("");
} }
/// @brief Open keyframes /// @brief Open keyframes
void FrameMain::OnOpenKeyframes (wxCommandEvent &) { void FrameMain::OnOpenKeyframes (wxCommandEvent &) {
// Pick file // Pick file
wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); 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); wxString filename = wxFileSelector(
if (filename.IsEmpty()) return; _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)); OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename));
// Load // Load
KeyFrameFile::Load(filename); VideoContext::Get()->LoadKeyframes(filename);
videoBox->videoSlider->Refresh(); videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update(); audioBox->audioDisplay->Update();
Refresh(); Refresh();
@ -817,7 +823,7 @@ void FrameMain::OnOpenKeyframes (wxCommandEvent &) {
/// @brief Close keyframes /// @brief Close keyframes
void FrameMain::OnCloseKeyframes (wxCommandEvent &) { void FrameMain::OnCloseKeyframes (wxCommandEvent &) {
VideoContext::Get()->CloseOverKeyFrames(); VideoContext::Get()->CloseKeyframes();
videoBox->videoSlider->Refresh(); videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update(); audioBox->audioDisplay->Update();
Refresh(); Refresh();
@ -831,8 +837,7 @@ void FrameMain::OnSaveKeyframes (wxCommandEvent &) {
if (filename.IsEmpty()) return; if (filename.IsEmpty()) return;
OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename));
// Save VideoContext::Get()->SaveKeyframes(filename);
KeyFrameFile::Save(filename);
} }
/// @brief Zoom levels /// @brief Zoom levels
@ -1064,76 +1069,59 @@ void FrameMain::OnAutomationMacro (wxCommandEvent &event) {
/// @brief Snap subs to video /// @brief Snap subs to video
void FrameMain::OnSnapSubsStartToVid (wxCommandEvent &) { void FrameMain::OnSnapSubsStartToVid (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) {
SubsGrid->SetSubsToVideo(true); SubsGrid->SetSubsToVideo(true);
}
} }
/// @brief DOCME /// @brief DOCME
void FrameMain::OnSnapSubsEndToVid (wxCommandEvent &) { void FrameMain::OnSnapSubsEndToVid (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) {
SubsGrid->SetSubsToVideo(false); SubsGrid->SetSubsToVideo(false);
}
} }
/// @brief Jump video to subs /// @brief Jump video to subs
void FrameMain::OnSnapVidToSubsStart (wxCommandEvent &) { void FrameMain::OnSnapVidToSubsStart (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) {
SubsGrid->SetVideoToSubs(true); SubsGrid->SetVideoToSubs(true);
}
} }
/// @brief DOCME /// @brief DOCME
void FrameMain::OnSnapVidToSubsEnd (wxCommandEvent &) { void FrameMain::OnSnapVidToSubsEnd (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded() && SubsGrid->GetSelection().Count() > 0) {
SubsGrid->SetVideoToSubs(false); SubsGrid->SetVideoToSubs(false);
}
} }
/// @brief Snap to scene /// @brief Snap to scene
void FrameMain::OnSnapToScene (wxCommandEvent &) { void FrameMain::OnSnapToScene (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded()) { VideoContext *con = VideoContext::Get();
if (!con->IsLoaded() || !con->KeyFramesLoaded()) return;
// Get frames // Get frames
wxArrayInt sel = SubsGrid->GetSelection(); wxArrayInt sel = SubsGrid->GetSelection();
int curFrame = VideoContext::Get()->GetFrameN(); int curFrame = con->GetFrameN();
int prev = 0; int prev = 0;
int next = 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];
if (frame == curFrame) { const std::vector<int> &keyframes = con->GetKeyFrames();
prev = frame; if (curFrame < keyframes.front()) {
if (i < n-1) next = keyframes[i+1]; next = keyframes.front();
else next = VideoContext::Get()->GetLength();
found = true;
break;
} }
else if (curFrame >= keyframes.back()) {
if (frame > curFrame) { prev = keyframes.back();
if (i != 0) prev = keyframes[i-1]; next = con->GetLength();
else prev = 0;
next = frame;
found = true;
break;
} }
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;
} }
// Last section?
if (!found) {
if (n > 0) prev = keyframes[n-1];
else prev = 0;
next = VideoContext::Get()->GetLength();
} }
// Get times // Get times
int start_ms = VFR_Output.GetTimeAtFrame(prev,true); int start_ms = con->TimeAtFrame(prev,agi::vfr::START);
int end_ms = VFR_Output.GetTimeAtFrame(next-1,false); int end_ms = con->TimeAtFrame(next-1,agi::vfr::END);
AssDialogue *cur; AssDialogue *cur;
// Update rows // Update rows
@ -1147,12 +1135,12 @@ void FrameMain::OnSnapToScene (wxCommandEvent &) {
SubsGrid->editBox->Update(true); SubsGrid->editBox->Update(true);
SubsGrid->ass->FlagAsModified(_("snap to scene")); SubsGrid->ass->FlagAsModified(_("snap to scene"));
SubsGrid->CommitChanges(); SubsGrid->CommitChanges();
}
} }
/// @brief Shift to frame /// @brief Shift to frame
void FrameMain::OnShiftToFrame (wxCommandEvent &) { void FrameMain::OnShiftToFrame (wxCommandEvent &) {
if (VideoContext::Get()->IsLoaded()) { if (!VideoContext::Get()->IsLoaded()) return;
wxArrayInt sels = SubsGrid->GetSelection(); wxArrayInt sels = SubsGrid->GetSelection();
size_t n=sels.Count(); size_t n=sels.Count();
if (n == 0) return; if (n == 0) return;
@ -1160,7 +1148,7 @@ void FrameMain::OnShiftToFrame (wxCommandEvent &) {
// Get shifting in ms // Get shifting in ms
AssDialogue *cur = SubsGrid->GetDialogue(sels[0]); AssDialogue *cur = SubsGrid->GetDialogue(sels[0]);
if (!cur) return; if (!cur) return;
int shiftBy = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),true) - cur->Start.GetMS(); int shiftBy = VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN(),agi::vfr::START) - cur->Start.GetMS();
// Update // Update
for (size_t i=0;i<n;i++) { for (size_t i=0;i<n;i++) {
@ -1175,7 +1163,6 @@ void FrameMain::OnShiftToFrame (wxCommandEvent &) {
SubsGrid->ass->FlagAsModified(_("shift to frame")); SubsGrid->ass->FlagAsModified(_("shift to frame"));
SubsGrid->CommitChanges(); SubsGrid->CommitChanges();
SubsGrid->editBox->Update(true,false); SubsGrid->editBox->Update(true,false);
}
} }
/// @brief Undo /// @brief Undo

View File

@ -34,16 +34,10 @@
/// @ingroup main_headers video_input /// @ingroup main_headers video_input
/// ///
#pragma once #pragma once
//////////
// Headers
#include "aegisub.h"
#include "vfr.h"
#include "video_frame.h" #include "video_frame.h"
#include <libaegisub/vfr.h>
/// @class VideoProvider /// @class VideoProvider
/// @brief DOCME /// @brief DOCME
@ -51,62 +45,31 @@
/// DOCME /// DOCME
class VideoProvider { class VideoProvider {
public: public:
/// @brief // Virtual destructor
/// @return
///
virtual ~VideoProvider() {} virtual ~VideoProvider() {}
// Override this method to actually get frames // Override this method to actually get frames
virtual const AegiVideoFrame GetFrame(int n)=0; virtual const AegiVideoFrame GetFrame(int n)=0;
// Override the following methods to get video information: // Override the following methods to get video information:
virtual int GetPosition()=0; // Get the number of the last frame loaded virtual int GetPosition() const=0; ///< Get the number of the last frame loaded
virtual int GetFrameCount()=0; // Get total number of frames virtual int GetFrameCount() const=0; ///< Get total number of frames
virtual int GetWidth()=0; // Returns the video width in pixels virtual int GetWidth() const=0; ///< Returns the video width in pixels
virtual int GetHeight()=0; // Returns the video height in pixels virtual int GetHeight() const=0; ///< Returns the video height in pixels
virtual double GetFPS()=0; // Get framerate in frames per second virtual agi::vfr::Framerate GetFPS() const=0; ///< Get frame rate
virtual bool AreKeyFramesLoaded()=0; // Returns true if keyframe info is loaded, false otherwise virtual std::vector<int> GetKeyFrames() const=0;///< Returns list of keyframes
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
/// @brief // Use this to set any post-loading warnings, such as "being loaded with unreliable seeking" /// @brief Use this to set any post-loading warnings, such as "being loaded with unreliable seeking"
/// @return virtual wxString GetWarning() const { return L""; }
///
virtual wxString GetWarning() { return L""; }
/// @brief // Name of decoder, e.g. "Avisynth/FFMpegSource"
/// @return
///
virtual wxString GetDecoderName() { return L"Unknown"; }
/// @brief Name of decoder, e.g. "Avisynth/FFMpegSource"
virtual wxString GetDecoderName() const = 0;
/// @brief Does this provider want Aegisub to cache video frames? /// @brief Does this provider want Aegisub to cache video frames?
/// @return Returns true if caching is desired, false otherwise. /// @return Returns true if caching is desired, false otherwise.
virtual bool WantsCaching() { return false; } virtual bool WantsCaching() const { 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
}; };
/// @class VideoProviderFactory /// @class VideoProviderFactory
/// @brief DOCME /// @brief DOCME
/// ///
@ -119,5 +82,3 @@ public:
virtual ~VideoProviderFactory() {} virtual ~VideoProviderFactory() {}
virtual VideoProvider *CreateProvider(wxString video)=0; virtual VideoProvider *CreateProvider(wxString video)=0;
}; };

View File

@ -34,8 +34,6 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -48,19 +46,11 @@
#include "options.h" #include "options.h"
#include "text_file_reader.h" #include "text_file_reader.h"
#include "text_file_writer.h" #include "text_file_writer.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
std::vector<int> KeyFrameFile::Load(wxString filename) {
/// @brief Load Keyframes
/// @param filename
///
void KeyFrameFile::Load(wxString filename) {
// Load
try { try {
// Open file std::vector<int> keyFrames;
wxArrayInt keyFrames;
keyFrames.Empty();
TextFileReader file(filename,_T("ASCII")); TextFileReader file(filename,_T("ASCII"));
wxString cur = file.ReadLineFromFile(); wxString cur = file.ReadLineFromFile();
@ -71,53 +61,36 @@ void KeyFrameFile::Load(wxString filename) {
else if (cur.StartsWith(_T("#options:"))) { Openx264KeyFrames(file, keyFrames); } else if (cur.StartsWith(_T("#options:"))) { Openx264KeyFrames(file, keyFrames); }
else { throw(_T("Invalid or unsupported keyframes file.")); } 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)); config::mru->Add("Keyframes", STD_STR(filename));
return keyFrames;
} }
// Fail // Fail
catch (const wchar_t *error) { catch (const wchar_t *error) {
wxString err(error); wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
wxMessageBox(err, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
} }
catch (...) { catch (...) {
wxMessageBox(_T("Unknown error"), _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); wxMessageBox(_T("Unknown error"), _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
} }
return std::vector<int>();
} }
void KeyFrameFile::Save(wxString filename, std::vector<int> const& keyFrames) {
/// @brief Save Keyframes
/// @param filename
///
void KeyFrameFile::Save(wxString filename) {
// Get keyframes
wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames();
// Write header
TextFileWriter file(filename,_T("ASCII")); TextFileWriter file(filename,_T("ASCII"));
file.WriteLineToFile(_T("# keyframe format v1")); 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.size();i++) {
for (unsigned int i=0;i<keyFrames.Count();i++) {
file.WriteLineToFile(wxString::Format(_T("%i"),keyFrames[i])); file.WriteLineToFile(wxString::Format(_T("%i"),keyFrames[i]));
} }
// Add to recent
config::mru->Add("Keyframes", STD_STR(filename)); config::mru->Add("Keyframes", STD_STR(filename));
} }
/// @brief Aegisub keyframes file /// @brief Aegisub keyframes file
/// @param file /// @param file
/// @param keyFrames /// @param keyFrames
/// ///
void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, std::vector<int>& keyFrames)
{ {
double fps; double fps;
wxString cur = file.ReadLineFromFile(); wxString cur = file.ReadLineFromFile();
@ -129,10 +102,8 @@ void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames
if (fps == 0.0) throw _T("Invalid FPS."); if (fps == 0.0) throw _T("Invalid FPS.");
// Set FPS // Set FPS
if (!VideoContext::Get()->IsLoaded()) { if (!VideoContext::Get()->TimecodesLoaded()) {
VideoContext::Get()->SetFPS(fps); VideoContext::Get()->ovrFPS = fps;
VFR_Input.SetCFR(fps);
if (!VFR_Output.IsLoaded()) VFR_Output.SetCFR(fps);
} }
// Read lines // Read lines
@ -141,18 +112,16 @@ void KeyFrameFile::OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames
if (!cur.IsEmpty() && !cur.StartsWith(_T("#")) && cur.IsNumber()) { if (!cur.IsEmpty() && !cur.StartsWith(_T("#")) && cur.IsNumber()) {
long temp; long temp;
cur.ToLong(&temp); cur.ToLong(&temp);
keyFrames.Add(temp); keyFrames.push_back(temp);
} }
} }
} }
/// @brief XviD stats file /// @brief XviD stats file
/// @param file /// @param file
/// @param keyFrames /// @param keyFrames
/// ///
void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, std::vector<int>& keyFrames)
{ {
wxString cur = file.ReadLineFromFile(); wxString cur = file.ReadLineFromFile();
unsigned int count = 0; unsigned int count = 0;
@ -160,7 +129,7 @@ void KeyFrameFile::OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames
// Read lines // Read lines
while (file.HasMoreLines()) { while (file.HasMoreLines()) {
if (cur.StartsWith(_T("i"))) { if (cur.StartsWith(_T("i"))) {
keyFrames.Add(count); keyFrames.push_back(count);
count++; count++;
} }
else if (cur.StartsWith(_T("p")) || cur.StartsWith(_T("b"))) { 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 /// @brief DivX stats file
/// @param file /// @param file
/// @param keyFrames /// @param keyFrames
/// ///
void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames) void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, std::vector<int>& keyFrames)
{ {
wxString cur = file.ReadLineFromFile(); wxString cur = file.ReadLineFromFile();
unsigned int count = 0; unsigned int count = 0;
@ -184,7 +152,7 @@ void KeyFrameFile::OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames
while (file.HasMoreLines()) while (file.HasMoreLines())
{ {
if (cur.Contains(_T("I"))) { if (cur.Contains(_T("I"))) {
keyFrames.Add(count); keyFrames.push_back(count);
count++; count++;
} }
else if (cur.Contains(_T("P")) || cur.Contains(_T("B"))) { 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 /// @brief x264 stats file
/// @param file /// @param file
/// @param keyFrames /// @param keyFrames
/// ///
void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames) void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, std::vector<int>& keyFrames)
{ {
wxString cur = file.ReadLineFromFile(); wxString cur = file.ReadLineFromFile();
unsigned int count = 0; unsigned int count = 0;
@ -210,7 +177,7 @@ void KeyFrameFile::Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames
{ {
pos = cur.Find(_T("type:")); pos = cur.Find(_T("type:"));
if (cur.Mid(pos,6).Right(1).Lower() == (_T("i"))) { if (cur.Mid(pos,6).Right(1).Lower() == (_T("i"))) {
keyFrames.Add(count); keyFrames.push_back(count);
count++; count++;
} }
else if (cur.Mid(pos,6).Right(1).Lower() == (_T("p")) || cur.Mid(pos,6).Right(1).Lower() == (_T("b"))) { 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(); cur = file.ReadLineFromFile();
} }
} }

View File

@ -34,9 +34,6 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "text_file_reader.h" #include "text_file_reader.h"
@ -48,13 +45,13 @@
class KeyFrameFile class KeyFrameFile
{ {
public: public:
static void Load(wxString filename); static std::vector<int> Load(wxString filename);
static void Save(wxString filename); static void Save(wxString filename, std::vector<int> const& keyframes);
private: private:
static void OpenAegiKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); static void OpenAegiKeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
static void OpenXviDKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); static void OpenXviDKeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
static void OpenDivXKeyFrames(TextFileReader& file, wxArrayInt& keyFrames); static void OpenDivXKeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
static void Openx264KeyFrames(TextFileReader& file, wxArrayInt& keyFrames); static void Openx264KeyFrames(TextFileReader& file, std::vector<int>& keyFrames);
}; };

View File

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

View File

@ -34,9 +34,6 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -44,6 +41,7 @@
#include <stdint.h> #include <stdint.h>
#include <algorithm> #include <algorithm>
#include <iterator>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
@ -53,6 +51,7 @@
#include "ass_file.h" #include "ass_file.h"
#include "ass_time.h" #include "ass_time.h"
#include "dialog_progress.h" #include "dialog_progress.h"
#include <libaegisub/vfr.h>
#include "mkv_wrap.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 /// @brief Set target to timecodes
/// @param target /// @param target
/// @return /// @return
/// ///
void MatroskaWrapper::SetToTimecodes(FrameRate &target) { void MatroskaWrapper::SetToTimecodes(agi::vfr::Framerate &target) {
// Enough frames? if (timecodes.size() <= 1) return;
int frames = timecodes.size();
if (frames <= 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; std::vector<int> times;
for (int i=0;i<frames;i++) times.push_back(int(timecodes[i]+0.5)); times.reserve(timecodes.size());
target.SetVFR(times); 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 /// @ingroup video_input
/// ///
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -48,14 +43,9 @@
#endif #endif
#include "MatroskaParser.h" #include "MatroskaParser.h"
#include "vfr.h"
//////////////
// Prototypes
class AssFile; class AssFile;
namespace agi { namespace vfr { class Framerate; } }
/// DOCME /// DOCME
/// @class MkvStdIO /// @class MkvStdIO
@ -161,7 +151,7 @@ public:
void Close(); void Close();
void Parse(); void Parse();
void SetToTimecodes(FrameRate &target); void SetToTimecodes(agi::vfr::Framerate &target);
/// @brief DOCME /// @brief DOCME
/// @return /// @return

View File

@ -299,9 +299,6 @@ void SubsEditBox::Update (bool timeOnly,bool weak) {
// Audio // Audio
if (!weak) audio->SetDialogue(grid,curdiag,grid->GetDialogueIndex(curdiag)); if (!weak) audio->SetDialogue(grid,curdiag,grid->GetDialogueIndex(curdiag));
// Video
VideoContext::Get()->curLine = curdiag;
TextEdit->EmptyUndoBuffer(); TextEdit->EmptyUndoBuffer();
} }
else enabled = false; else enabled = false;
@ -550,7 +547,7 @@ void SubsEditBox::SetControlsState (bool state) {
/// @brief Disables or enables frame timing /// @brief Disables or enables frame timing
/// ///
void SubsEditBox::UpdateFrameTiming () { void SubsEditBox::UpdateFrameTiming () {
if (VideoContext::Get()->IsLoaded()) ByFrame->Enable(enabled); if (VideoContext::Get()->TimecodesLoaded()) ByFrame->Enable(enabled);
else { else {
ByFrame->Enable(false); ByFrame->Enable(false);
ByTime->SetValue(true); ByTime->SetValue(true);

View File

@ -34,9 +34,6 @@
/// @ingroup main_ui /// @ingroup main_ui
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -61,13 +58,9 @@
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
///////////////
// Event table
BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid) BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid)
EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown) EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown)
EVT_MENU(MENU_SWAP,SubtitlesGrid::OnSwap) EVT_MENU(MENU_SWAP,SubtitlesGrid::OnSwap)
@ -171,14 +164,14 @@ void SubtitlesGrid::OnPopupMenu(bool alternate) {
state = (sels == 1); state = (sels == 1);
menu.Append(MENU_INSERT_BEFORE,_("&Insert (before)"),_T("Inserts a line before current"))->Enable(state); 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); 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_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.Append(MENU_INSERT_AFTER_VIDEO,_("Insert at video time (after)"),_T("Inserts a line after current, starting at video time"))->Enable(state);
menu.AppendSeparator(); menu.AppendSeparator();
// Duplicate selection // Duplicate selection
menu.Append(MENU_DUPLICATE,_("&Duplicate"),_("Duplicate the selected lines"))->Enable(continuous); 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); menu.Append(MENU_SPLIT_BY_KARAOKE,_("Split (by karaoke)"),_("Uses karaoke timing to split line into multiple smaller lines"))->Enable(sels > 0);
// Swaps selection // Swaps selection
@ -318,7 +311,7 @@ void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) {
} }
// Duplicate and shift // Duplicate and shift
if (VFR_Output.IsLoaded()) { if (context->TimecodesLoaded()) {
if (Hotkeys.IsPressed(_T("Grid duplicate and shift one frame"))) { if (Hotkeys.IsPressed(_T("Grid duplicate and shift one frame"))) {
DuplicateLines(n,n2,true); DuplicateLines(n,n2,true);
return; return;
@ -518,7 +511,7 @@ void SubtitlesGrid::OnInsertBeforeVideo (wxCommandEvent &event) {
// Create line to add // Create line to add
AssDialogue *def = new AssDialogue; 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->Start.SetMS(video_ms);
def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt()); def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt());
def->Style = GetDialogue(n)->Style; def->Style = GetDialogue(n)->Style;
@ -542,7 +535,7 @@ void SubtitlesGrid::OnInsertAfterVideo (wxCommandEvent &event) {
// Create line to add // Create line to add
AssDialogue *def = new AssDialogue; 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->Start.SetMS(video_ms);
def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt()); def->End.SetMS(video_ms+OPT_GET("Timing/Default Duration")->GetInt());
def->Style = GetDialogue(n)->Style; def->Style = GetDialogue(n)->Style;
@ -819,7 +812,6 @@ void SubtitlesGrid::ClearMaps() {
void SubtitlesGrid::UpdateMaps() { void SubtitlesGrid::UpdateMaps() {
BeginBatch(); BeginBatch();
VideoContext::Get()->curLine = NULL;
line_iter_map.clear(); line_iter_map.clear();
BaseGrid::ClearMaps(); BaseGrid::ClearMaps();
@ -1244,9 +1236,9 @@ void SubtitlesGrid::DuplicateLines(int n1,int n2,bool nextFrame) {
// Shift to next frame // Shift to next frame
if (nextFrame) { if (nextFrame) {
int posFrame = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false) + 1; int posFrame = context->FrameAtTime(cur->End.GetMS(),agi::vfr::END) + 1;
cur->Start.SetMS(VFR_Output.GetTimeAtFrame(posFrame,true)); cur->Start.SetMS(context->TimeAtFrame(posFrame,agi::vfr::START));
cur->End.SetMS(VFR_Output.GetTimeAtFrame(posFrame,false)); cur->End.SetMS(context->TimeAtFrame(posFrame,agi::vfr::END));
} }
// Insert // Insert
@ -1292,8 +1284,8 @@ void SubtitlesGrid::ShiftLineByTime(int n,int len,int type) {
void SubtitlesGrid::ShiftLineByFrames(int n,int len,int type) { void SubtitlesGrid::ShiftLineByFrames(int n,int len,int type) {
AssDialogue *cur = GetDialogue(n); AssDialogue *cur = GetDialogue(n);
if (type != 2) cur->Start.SetMS(VFR_Output.GetTimeAtFrame(len + VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true),true)); 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(VFR_Output.GetTimeAtFrame(len + VFR_Output.GetFrameAtTime(cur->End.GetMS(),false),false)); 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 /// @param videoOnly
/// ///
void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) { void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) {
if (VideoContext::Get()->IsLoaded() || force) { if (context->IsLoaded() || force) {
// Check if it's playing // Check if it's playing
bool playing = false; bool playing = false;
if (VideoContext::Get()->IsPlaying()) { if (context->IsPlaying()) {
playing = true; playing = true;
VideoContext::Get()->Stop(); context->Stop();
} }
// Update video // Update video
if (VideoContext::Get()->IsLoaded()) VideoContext::Get()->Refresh(); if (context->IsLoaded()) context->Refresh();
// Resume play // Resume play
if (playing) VideoContext::Get()->Play(); if (playing) context->Play();
} }
if (!videoOnly) { if (!videoOnly) {
@ -1422,18 +1414,15 @@ void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) {
} }
} }
/// @brief Set start to video pos /// @brief Set start to video pos
/// @param start /// @param start
/// @return /// @return
/// ///
void SubtitlesGrid::SetSubsToVideo(bool start) { void SubtitlesGrid::SetSubsToVideo(bool start) {
// Check if it's OK to do it if (!context->IsLoaded()) return;
if (!VFR_Output.IsLoaded()) return;
// Get new time // 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 // Update selection
wxArrayInt sel = GetSelection(); wxArrayInt sel = GetSelection();
@ -1468,9 +1457,9 @@ void SubtitlesGrid::SetVideoToSubs(bool start) {
AssDialogue *cur = GetDialogue(sel[0]); AssDialogue *cur = GetDialogue(sel[0]);
if (cur) { if (cur) {
if (start) if (start)
VideoContext::Get()->JumpToTime(cur->Start.GetMS()); context->JumpToTime(cur->Start.GetMS());
else 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 /// @ingroup main_ui
/// ///
////////////
// Includes
#ifndef AGI_PRE #ifndef AGI_PRE
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -54,9 +49,6 @@
#include "audio_provider_manager.h" #include "audio_provider_manager.h"
#include "base_grid.h" #include "base_grid.h"
//////////////
// Prototypes
class AssFile; class AssFile;
class AssEntry; class AssEntry;
class AssDialogue; class AssDialogue;
@ -64,13 +56,9 @@ class SubsEditBox;
class FrameMain; class FrameMain;
class AudioDisplay; class AudioDisplay;
/// DOCME /// DOCME
typedef std::list<AssEntry*>::iterator entryIter; typedef std::list<AssEntry*>::iterator entryIter;
/// DOCME /// DOCME
/// @class SubtitlesGrid /// @class SubtitlesGrid
/// @brief DOCME /// @brief DOCME

View File

@ -34,9 +34,6 @@
/// @ingroup subtitle_io /// @ingroup subtitle_io
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -55,8 +52,7 @@
#include "subtitle_format_transtation.h" #include "subtitle_format_transtation.h"
#include "subtitle_format_ttxt.h" #include "subtitle_format_ttxt.h"
#include "subtitle_format_txt.h" #include "subtitle_format_txt.h"
#include "vfr.h" #include "video_context.h"
/// @brief Constructor /// @brief Constructor
/// ///
@ -66,24 +62,18 @@ SubtitleFormat::SubtitleFormat() {
isCopy = false; isCopy = false;
} }
/// @brief Destructor /// @brief Destructor
/// ///
SubtitleFormat::~SubtitleFormat () { SubtitleFormat::~SubtitleFormat () {
Remove(); Remove();
} }
/// DOCME /// DOCME
std::list<SubtitleFormat*> SubtitleFormat::formats; std::list<SubtitleFormat*> SubtitleFormat::formats;
/// DOCME /// DOCME
bool SubtitleFormat::loaded = false; bool SubtitleFormat::loaded = false;
/// @brief Set target /// @brief Set target
/// @param file /// @param file
/// ///
@ -94,8 +84,6 @@ void SubtitleFormat::SetTarget(AssFile *file) {
assFile = file; assFile = file;
} }
/// @brief Create copy /// @brief Create copy
/// ///
void SubtitleFormat::CreateCopy() { void SubtitleFormat::CreateCopy() {
@ -103,8 +91,6 @@ void SubtitleFormat::CreateCopy() {
isCopy = true; isCopy = true;
} }
/// @brief Clear copy /// @brief Clear copy
/// ///
void SubtitleFormat::ClearCopy() { void SubtitleFormat::ClearCopy() {
@ -115,16 +101,12 @@ void SubtitleFormat::ClearCopy() {
} }
} }
/// @brief Clear subtitles /// @brief Clear subtitles
/// ///
void SubtitleFormat::Clear() { void SubtitleFormat::Clear() {
assFile->Clear(); assFile->Clear();
} }
/// @brief Load default /// @brief Load default
/// @param defline /// @param defline
/// ///
@ -132,8 +114,6 @@ void SubtitleFormat::LoadDefault(bool defline) {
assFile->LoadDefault(defline); assFile->LoadDefault(defline);
} }
/// @brief Add line /// @brief Add line
/// @param data /// @param data
/// @param group /// @param group
@ -143,8 +123,6 @@ void SubtitleFormat::AddLine(wxString data,wxString group,int &version,wxString
assFile->AddLine(data,group,version,outgroup); assFile->AddLine(data,group,version,outgroup);
} }
/// @brief Add formats /// @brief Add formats
/// ///
void SubtitleFormat::LoadFormats () { void SubtitleFormat::LoadFormats () {
@ -164,8 +142,6 @@ void SubtitleFormat::LoadFormats () {
loaded = true; loaded = true;
} }
/// @brief Destroy formats /// @brief Destroy formats
/// ///
void SubtitleFormat::DestroyFormats () { void SubtitleFormat::DestroyFormats () {
@ -176,8 +152,6 @@ void SubtitleFormat::DestroyFormats () {
formats.clear(); formats.clear();
} }
/// @brief Get an appropriate reader /// @brief Get an appropriate reader
/// @param filename /// @param filename
/// @return /// @return
@ -193,8 +167,6 @@ SubtitleFormat *SubtitleFormat::GetReader(wxString filename) {
return NULL; return NULL;
} }
/// @brief Get an appropriate writer /// @brief Get an appropriate writer
/// @param filename /// @param filename
/// @return /// @return
@ -210,8 +182,6 @@ SubtitleFormat *SubtitleFormat::GetWriter(wxString filename) {
return NULL; return NULL;
} }
/// @brief Register /// @brief Register
/// @return /// @return
/// ///
@ -223,8 +193,6 @@ void SubtitleFormat::Register() {
formats.push_back(this); formats.push_back(this);
} }
/// @brief Remove /// @brief Remove
/// @return /// @return
/// ///
@ -238,8 +206,6 @@ void SubtitleFormat::Remove() {
} }
} }
/// @brief Get read wildcards /// @brief Get read wildcards
/// @return /// @return
/// ///
@ -247,8 +213,6 @@ wxArrayString SubtitleFormat::GetReadWildcards() {
return wxArrayString(); return wxArrayString();
} }
/// @brief Get write wildcards /// @brief Get write wildcards
/// @return /// @return
/// ///
@ -256,8 +220,6 @@ wxArrayString SubtitleFormat::GetWriteWildcards() {
return wxArrayString(); return wxArrayString();
} }
/// @brief Get wildcard list /// @brief Get wildcard list
/// @param mode /// @param mode
/// @return /// @return
@ -313,8 +275,6 @@ wxString SubtitleFormat::GetWildcards(int mode) {
return final; return final;
} }
/// @brief Ask the user to enter the FPS /// @brief Ask the user to enter the FPS
/// @param showSMPTE /// @param showSMPTE
/// @return /// @return
@ -325,11 +285,12 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
fps_rat.smpte_dropframe = false; // ensure it's false by default fps_rat.smpte_dropframe = false; // ensure it's false by default
// Video FPS // Video FPS
bool vidLoaded = VFR_Output.IsLoaded(); VideoContext *context = VideoContext::Get();
bool vidLoaded = context->TimecodesLoaded();
if (vidLoaded) { if (vidLoaded) {
wxString vidFPS; wxString vidFPS;
if (VFR_Output.GetFrameRateType() == VFR) vidFPS = _T("VFR"); if (context->FPS().IsVFR()) vidFPS = _T("VFR");
else vidFPS = wxString::Format(_T("%.3f"),VFR_Output.GetAverage()); else vidFPS = wxString::Format(_T("%.3f"),context->FPS().FPS());
choices.Add(wxString::Format(_T("From video (%s)"),vidFPS.c_str())); choices.Add(wxString::Format(_T("From video (%s)"),vidFPS.c_str()));
} }
@ -403,16 +364,12 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
return fps_rat; return fps_rat;
} }
/// @brief Sort lines /// @brief Sort lines
/// ///
void SubtitleFormat::SortLines() { void SubtitleFormat::SortLines() {
AssFile::Sort(*Line); AssFile::Sort(*Line);
} }
/// @brief Convert tags /// @brief Convert tags
/// @param format /// @param format
/// @param lineEnd /// @param lineEnd
@ -438,8 +395,6 @@ void SubtitleFormat::ConvertTags(int format,const wxString &lineEnd,bool mergeLi
} }
} }
/// @brief Remove all comment lines /// @brief Remove all comment lines
/// ///
void SubtitleFormat::StripComments() { void SubtitleFormat::StripComments() {
@ -458,8 +413,6 @@ void SubtitleFormat::StripComments() {
} }
} }
/// @brief Remove all non-dialogue lines /// @brief Remove all non-dialogue lines
/// ///
void SubtitleFormat::StripNonDialogue() { void SubtitleFormat::StripNonDialogue() {
@ -477,8 +430,6 @@ void SubtitleFormat::StripNonDialogue() {
} }
} }
/// @brief Helper function for RecombineOverlaps() /// @brief Helper function for RecombineOverlaps()
/// @param list /// @param list
/// @param next /// @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 /// @brief Split and merge lines so there are no overlapping lines
/// ///
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge /// 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 /// @brief Merge identical lines that follow each other
/// ///
void SubtitleFormat::MergeIdentical() { void SubtitleFormat::MergeIdentical() {
@ -608,6 +556,3 @@ void SubtitleFormat::MergeIdentical() {
} }
} }
} }

View File

@ -34,12 +34,8 @@
/// @ingroup subtitle_io /// @ingroup subtitle_io
/// ///
#pragma once #pragma once
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <list> #include <list>
@ -49,22 +45,15 @@
#include <libaegisub/exception.h> #include <libaegisub/exception.h>
//////////////
// Prototypes
class AssFile; class AssFile;
class AssEntry; class AssEntry;
/// DOCME /// DOCME
/// @class SubtitleFormat /// @class SubtitleFormat
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class SubtitleFormat { class SubtitleFormat {
private:
/// DOCME /// DOCME
bool isCopy; bool isCopy;
@ -74,7 +63,6 @@ private:
void Register(); void Register();
void Remove(); void Remove();
/// DOCME /// DOCME
static std::list<SubtitleFormat*> formats; static std::list<SubtitleFormat*> formats;
@ -82,7 +70,6 @@ private:
static bool loaded; static bool loaded;
protected: protected:
/// DOCME /// DOCME
struct FPSRational { struct FPSRational {
@ -96,7 +83,6 @@ protected:
bool smpte_dropframe; bool smpte_dropframe;
}; };
/// DOCME /// DOCME
std::list<AssEntry*> *Line; std::list<AssEntry*> *Line;
@ -131,7 +117,6 @@ public:
static wxString GetWildcards(int mode); static wxString GetWildcards(int mode);
/// @brief DOCME /// @brief DOCME
/// @param filename /// @param filename
/// @return /// @return
@ -162,6 +147,4 @@ public:
static void DestroyFormats(); static void DestroyFormats();
}; };
DEFINE_SIMPLE_EXCEPTION(SubtitleFormatParseError, agi::InvalidInputException, "subtitle_io/parse/generic") DEFINE_SIMPLE_EXCEPTION(SubtitleFormatParseError, agi::InvalidInputException, "subtitle_io/parse/generic")

View File

@ -34,9 +34,6 @@
/// @ingroup subtitle_io /// @ingroup subtitle_io
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -48,42 +45,22 @@
#include "subtitle_format_microdvd.h" #include "subtitle_format_microdvd.h"
#include "text_file_reader.h" #include "text_file_reader.h"
#include "text_file_writer.h" #include "text_file_writer.h"
#include "vfr.h" #include "video_context.h"
/// @brief Get format name
/// @return
///
wxString MicroDVDSubtitleFormat::GetName() { wxString MicroDVDSubtitleFormat::GetName() {
return _T("MicroDVD"); return _T("MicroDVD");
} }
/// @brief Get read wildcards
/// @return
///
wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() { wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() {
wxArrayString formats; wxArrayString formats;
formats.Add(_T("sub")); formats.Add(_T("sub"));
return formats; return formats;
} }
/// @brief Get write wildcards
/// @return
///
wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() { wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() {
return GetReadWildcards(); return GetReadWildcards();
} }
/// @brief Can read a file?
/// @param filename
/// @return
///
bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) { bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) {
// Return false immediately if extension is wrong // Return false immediately if extension is wrong
if (filename.Right(4).Lower() != _T(".sub")) return false; if (filename.Right(4).Lower() != _T(".sub")) return false;
@ -98,43 +75,25 @@ bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) {
return false; return false;
} }
/// @brief Can write a file?
/// @param filename
/// @return
///
bool MicroDVDSubtitleFormat::CanWriteFile(wxString filename) { bool MicroDVDSubtitleFormat::CanWriteFile(wxString filename) {
return (filename.Right(4).Lower() == _T(".sub")); return (filename.Right(4).Lower() == _T(".sub"));
} }
/// @brief Read a file
/// @param filename
/// @param forceEncoding
/// @return
///
void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) { void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) {
// Load and prepare regexp
TextFileReader file(filename); TextFileReader file(filename);
wxRegEx exp(_T("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$"),wxRE_ADVANCED); wxRegEx exp(_T("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$"),wxRE_ADVANCED);
// Load default
LoadDefault(false); LoadDefault(false);
// Prepare conversion agi::vfr::Framerate cfr;
FrameRate cfr; const agi::vfr::Framerate *rate = &cfr;
FrameRate *rate = &cfr;
// Loop
bool isFirst = true; bool isFirst = true;
FPSRational fps_rat; FPSRational fps_rat;
double fps = 0.0; double fps = 0.0;
while (file.HasMoreLines()) { while (file.HasMoreLines()) {
wxString line = file.ReadLineFromFile(); wxString line = file.ReadLineFromFile();
if (exp.Matches(line)) { if (exp.Matches(line)) {
// Parse
long f1,f2; long f1,f2;
exp.GetMatch(line,1).ToLong(&f1); exp.GetMatch(line,1).ToLong(&f1);
exp.GetMatch(line,2).ToLong(&f2); exp.GetMatch(line,2).ToLong(&f2);
@ -147,7 +106,7 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding)
try { try {
text.ToDouble(&fps); text.ToDouble(&fps);
} }
catch (...) {} catch (...) { }
} }
isFirst = false; isFirst = false;
@ -155,24 +114,22 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding)
if (fps <= 0.0) { if (fps <= 0.0) {
fps_rat = AskForFPS(); fps_rat = AskForFPS();
if (fps_rat.num == 0) return; if (fps_rat.num == 0) return;
else if (fps_rat.num > 0) cfr.SetCFR(double(fps_rat.num)/double(fps_rat.den)); else if (fps_rat.num > 0) cfr = double(fps_rat.num)/fps_rat.den;
else rate = &VFR_Output; else rate = &VideoContext::Get()->FPS();
} }
else { else {
cfr.SetCFR(fps); cfr = fps;
continue; continue;
} }
} }
// Start and end times // Start and end times
int start,end; int start,end;
start = rate->GetTimeAtFrame(f1,true); start = rate->TimeAtFrame(f1,agi::vfr::START);
end = rate->GetTimeAtFrame(f2,false); end = rate->TimeAtFrame(f2,agi::vfr::END);
// Process text
text.Replace(_T("|"),_T("\\N")); text.Replace(_T("|"),_T("\\N"));
// Create and insert line
AssDialogue *line = new AssDialogue(); AssDialogue *line = new AssDialogue();
line->group = _T("[Events]"); line->group = _T("[Events]");
line->Style = _T("Default"); 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) { void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
// Set FPS agi::vfr::Framerate cfr;
FrameRate cfr; const agi::vfr::Framerate *rate = &cfr;
FrameRate *rate = &cfr;
FPSRational fps_rat = AskForFPS(); FPSRational fps_rat = AskForFPS();
if (fps_rat.num == 0 || fps_rat.den == 0) return; if (fps_rat.num == 0 || fps_rat.den == 0) return;
double fps = double(fps_rat.num) / double(fps_rat.den); double fps = double(fps_rat.num) / fps_rat.den;
if (fps > 0.0) cfr.SetCFR(fps); if (fps > 0.0) cfr = fps;
else rate = &VFR_Output; else rate = &VideoContext::Get()->FPS();
// Convert file // Convert file
CreateCopy(); CreateCopy();
@ -208,12 +159,11 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
MergeIdentical(); MergeIdentical();
ConvertTags(1,_T("|")); ConvertTags(1,_T("|"));
// Open file
TextFileWriter file(filename,encoding); TextFileWriter file(filename,encoding);
// Write FPS line // Write FPS line
if (rate->GetFrameRateType() != VFR) { if (!rate->IsVFR()) {
file.WriteLineToFile(wxString::Format(_T("{1}{1}%.6f"),rate->GetAverage())); file.WriteLineToFile(wxString::Format(_T("{1}{1}%.6f"),rate->FPS()));
} }
// Write lines // Write lines
@ -221,17 +171,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) { for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur); AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
if (current && !current->Comment) { if (current && !current->Comment) {
// Prepare data int start = rate->FrameAtTime(current->Start.GetMS(),agi::vfr::START);
int start = rate->GetFrameAtTime(current->Start.GetMS(),true); int end = rate->FrameAtTime(current->End.GetMS(),agi::vfr::END);
int end = rate->GetFrameAtTime(current->End.GetMS(),false);
// Write data
file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,current->Text.c_str())); file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,current->Text.c_str()));
} }
} }
// Clean up
ClearCopy(); ClearCopy();
} }

View File

@ -34,14 +34,8 @@
/// @ingroup subtitle_io /// @ingroup subtitle_io
/// ///
///////////
// Headers
#include "subtitle_format.h" #include "subtitle_format.h"
/// DOCME /// DOCME
/// @class MicroDVDSubtitleFormat /// @class MicroDVDSubtitleFormat
/// @brief DOCME /// @brief DOCME
@ -59,5 +53,3 @@ public:
bool CanWriteFile(wxString filename); bool CanWriteFile(wxString filename);
void WriteFile(wxString filename,wxString encoding); void WriteFile(wxString filename,wxString encoding);
}; };

View File

@ -47,7 +47,6 @@
#include "text_file_writer.h" #include "text_file_writer.h"
#include "video_context.h" #include "video_context.h"
/// @brief Constructor /// @brief Constructor
/// @param type /// @param type
/// ///
@ -56,17 +55,14 @@ CSRISubtitlesProvider::CSRISubtitlesProvider(wxString type) {
instance = NULL; instance = NULL;
} }
/// @brief Destructor /// @brief Destructor
/// ///
CSRISubtitlesProvider::~CSRISubtitlesProvider() { CSRISubtitlesProvider::~CSRISubtitlesProvider() {
if (!tempfile.empty()) wxRemoveFile(tempfile);
if (instance) csri_close(instance); if (instance) csri_close(instance);
instance = NULL; instance = NULL;
} }
/// @brief Load subtitles /// @brief Load subtitles
/// @param subs /// @param subs
/// ///
@ -108,14 +104,16 @@ void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs) {
// Open from disk // Open from disk
else { else {
wxString subsFileName = VideoContext::Get()->GetTempWorkFile(); if (tempfile.empty()) {
subs->Save(subsFileName,false,false,wxSTRING_ENCODING); tempfile = wxFileName::CreateTempFileName(_T("aegisub"));
instance = csri_open_file(renderer,subsFileName.mb_str(wxConvUTF8),NULL); wxRemoveFile(tempfile);
tempfile += L".ass";
}
subs->Save(tempfile,false,false,wxSTRING_ENCODING);
instance = csri_open_file(renderer,tempfile.utf8_str(),NULL);
} }
} }
/// @brief Draw subtitles /// @brief Draw subtitles
/// @param dst /// @param dst
/// @param time /// @param time
@ -155,8 +153,6 @@ void CSRISubtitlesProvider::DrawSubtitles(AegiVideoFrame &dst,double time) {
csri_render(instance,&frame,time); csri_render(instance,&frame,time);
} }
/// @brief Get CSRI subtypes /// @brief Get CSRI subtypes
/// ///
wxArrayString CSRISubtitlesProviderFactory::GetSubTypes() { wxArrayString CSRISubtitlesProviderFactory::GetSubTypes() {
@ -179,7 +175,4 @@ wxArrayString CSRISubtitlesProviderFactory::GetSubTypes() {
return final; return final;
} }
#endif // WITH_CSRI #endif // WITH_CSRI

View File

@ -34,15 +34,10 @@
/// @ingroup subtitle_rendering /// @ingroup subtitle_rendering
/// ///
///////////
// Headers
#ifdef WITH_CSRI #ifdef WITH_CSRI
#include "include/aegisub/subtitles_provider.h" #include "include/aegisub/subtitles_provider.h"
#ifdef WIN32 #ifdef WIN32
/// DOCME /// DOCME
#define CSRIAPI #define CSRIAPI
#endif #endif
@ -53,21 +48,19 @@
#include <csri/csri.h> #include <csri/csri.h>
#endif #endif
/// DOCME /// DOCME
/// @class CSRISubtitlesProvider /// @class CSRISubtitlesProvider
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class CSRISubtitlesProvider : public SubtitlesProvider { class CSRISubtitlesProvider : public SubtitlesProvider {
private:
/// DOCME /// DOCME
wxString subType; wxString subType;
/// DOCME /// DOCME
csri_inst *instance; csri_inst *instance;
wxString tempfile;
public: public:
CSRISubtitlesProvider(wxString subType); CSRISubtitlesProvider(wxString subType);
~CSRISubtitlesProvider(); ~CSRISubtitlesProvider();
@ -76,8 +69,6 @@ public:
void DrawSubtitles(AegiVideoFrame &dst,double time); void DrawSubtitles(AegiVideoFrame &dst,double time);
}; };
/// DOCME /// DOCME
/// @class CSRISubtitlesProviderFactory /// @class CSRISubtitlesProviderFactory
/// @brief DOCME /// @brief DOCME
@ -85,7 +76,6 @@ public:
/// DOCME /// DOCME
class CSRISubtitlesProviderFactory : public SubtitlesProviderFactory { class CSRISubtitlesProviderFactory : public SubtitlesProviderFactory {
public: public:
/// @brief DOCME /// @brief DOCME
/// @param subType /// @param subType
/// ///
@ -94,5 +84,3 @@ public:
}; };
#endif #endif

View File

@ -34,9 +34,6 @@
/// @ingroup custom_control /// @ingroup custom_control
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -51,8 +48,7 @@
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "timeedit_ctrl.h" #include "timeedit_ctrl.h"
#include "vfr.h" #include "video_context.h"
#ifdef __WXGTK__ #ifdef __WXGTK__
/// Use the multiline style only on wxGTK to workaround some wxGTK bugs with the default singleline style. /// 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 #define TimeEditWindowStyle wxTE_CENTRE
#endif #endif
/// @brief Constructor /// @brief Constructor
/// @param parent /// @param parent
/// @param id /// @param id
@ -114,9 +109,6 @@ wxTextCtrl(parent,id,value,pos,size,TimeEditWindowStyle | style,validator,name)
Connect(wxEVT_KILL_FOCUS,wxFocusEventHandler(TimeEdit::OnKillFocus)); Connect(wxEVT_KILL_FOCUS,wxFocusEventHandler(TimeEdit::OnKillFocus));
} }
///////////////
// Event table
BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl) BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl)
EVT_MOUSE_EVENTS(TimeEdit::OnMouseEvent) EVT_MOUSE_EVENTS(TimeEdit::OnMouseEvent)
EVT_KEY_DOWN(TimeEdit::OnKeyDown) EVT_KEY_DOWN(TimeEdit::OnKeyDown)
@ -124,30 +116,20 @@ BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl)
EVT_MENU(Time_Edit_Paste,TimeEdit::OnPaste) EVT_MENU(Time_Edit_Paste,TimeEdit::OnPaste)
END_EVENT_TABLE() END_EVENT_TABLE()
/// @brief Modified event /// @brief Modified event
/// @param event /// @param event
/// @return
///
void TimeEdit::OnModified(wxCommandEvent &event) { void TimeEdit::OnModified(wxCommandEvent &event) {
event.Skip(); event.Skip();
if (!ready) return; if (!ready) return;
Modified(); Modified();
} }
/// @brief Modified function /// @brief Modified function
/// @param byUser /// @param byUser
/// @return
///
void TimeEdit::Modified(bool byUser) { void TimeEdit::Modified(bool byUser) {
// Lock
if (!ready) return; if (!ready) return;
ready = false; ready = false;
// Update
if (byFrame) Update(); if (byFrame) Update();
else UpdateTime(byUser); else UpdateTime(byUser);
@ -156,13 +138,9 @@ void TimeEdit::Modified(bool byUser) {
SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour())); SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour()));
} }
modified = true; modified = true;
// Done
ready = true; ready = true;
} }
/// @brief Set time and update stuff /// @brief Set time and update stuff
/// @param ms /// @param ms
/// @param setModified /// @param setModified
@ -174,18 +152,14 @@ void TimeEdit::SetTime(int ms,bool setModified) {
if (setModified && oldMs != ms) Modified(false); if (setModified && oldMs != ms) Modified(false);
} }
/// @brief Toggles between set by frame and time /// @brief Toggles between set by frame and time
/// @param enable /// @param enable
/// @return
///
void TimeEdit::SetByFrame(bool enable) { void TimeEdit::SetByFrame(bool enable) {
if (enable == byFrame) return; if (enable == byFrame) return;
// By frames // By frames
if (enable) { if (enable) {
if (VFR_Output.IsLoaded()) { if (VideoContext::Get()->IsLoaded()) {
byFrame = true; byFrame = true;
UpdateText(); UpdateText();
} }
@ -198,22 +172,18 @@ void TimeEdit::SetByFrame(bool enable) {
} }
} }
/// @brief Update text to reflect time value /// @brief Update text to reflect time value
/// ///
void TimeEdit::UpdateText() { void TimeEdit::UpdateText() {
ready = false; ready = false;
if (byFrame) { 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)); SetValue(wxString::Format(_T("%i"),frame_n));
} }
else SetValue(time.GetASSFormated()); else SetValue(time.GetASSFormated());
ready = true; ready = true;
} }
/// @brief Update /// @brief Update
/// ///
void TimeEdit::Update() { void TimeEdit::Update() {
@ -221,7 +191,7 @@ void TimeEdit::Update() {
if (byFrame) { if (byFrame) {
long temp; long temp;
GetValue().ToLong(&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 // Update time if not on insertion mode
@ -238,8 +208,6 @@ void TimeEdit::Update() {
modified = false; modified = false;
} }
/// @brief Reads value from a text control and update it /// @brief Reads value from a text control and update it
/// @param byUser /// @param byUser
/// ///
@ -273,8 +241,6 @@ void TimeEdit::UpdateTime(bool byUser) {
} }
} }
/// @brief Key pressed /// @brief Key pressed
/// @param event /// @param event
/// ///
@ -316,8 +282,6 @@ void TimeEdit::OnKeyDown(wxKeyEvent &event) {
} }
} }
/// @brief Focus lost /// @brief Focus lost
/// @param event /// @param event
/// ///
@ -331,14 +295,10 @@ void TimeEdit::OnKillFocus(wxFocusEvent &event) {
event.Skip(); event.Skip();
} }
///// Mouse/copy/paste events down here ///// ///// Mouse/copy/paste events down here /////
/// @brief Mouse event /// @brief Mouse event
/// @param event /// @param event
/// @return
///
void TimeEdit::OnMouseEvent(wxMouseEvent &event) { void TimeEdit::OnMouseEvent(wxMouseEvent &event) {
// Right click context menu // Right click context menu
if (event.RightUp()) { if (event.RightUp()) {
@ -355,8 +315,6 @@ void TimeEdit::OnMouseEvent(wxMouseEvent &event) {
event.Skip(); event.Skip();
} }
/// @brief Menu Copy /// @brief Menu Copy
/// @param event /// @param event
/// ///
@ -367,8 +325,6 @@ void TimeEdit::OnCopy(wxCommandEvent &event) {
Refresh(); Refresh();
} }
/// @brief Menu Paste /// @brief Menu Paste
/// @param event /// @param event
/// ///
@ -378,10 +334,7 @@ void TimeEdit::OnPaste(wxCommandEvent &event) {
Refresh(); Refresh();
} }
/// @brief Copy to clipboard /// @brief Copy to clipboard
/// @return
/// ///
void TimeEdit::CopyTime() { void TimeEdit::CopyTime() {
// Frame // Frame
@ -397,8 +350,6 @@ void TimeEdit::CopyTime() {
} }
} }
/// @brief Paste from clipboard /// @brief Paste from clipboard
/// ///
void TimeEdit::PasteTime() { 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 "subs_grid.h"
#include "toggle_bitmap.h" #include "toggle_bitmap.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"

View File

@ -34,9 +34,6 @@
/// @ingroup video /// @ingroup video
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -63,6 +60,8 @@
#include "ass_time.h" #include "ass_time.h"
#include "audio_display.h" #include "audio_display.h"
#include "compat.h" #include "compat.h"
#include "keyframe.h"
#include <libaegisub/access.h>
#include "main.h" #include "main.h"
#include "mkv_wrap.h" #include "mkv_wrap.h"
#include "options.h" #include "options.h"
@ -71,97 +70,64 @@
#include "subs_grid.h" #include "subs_grid.h"
#include "subtitles_provider_manager.h" #include "subtitles_provider_manager.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
#include "video_provider_manager.h" #include "video_provider_manager.h"
/// IDs
///////
// IDs
enum { enum {
/// DOCME
VIDEO_PLAY_TIMER = 1300 VIDEO_PLAY_TIMER = 1300
}; };
///////////////
// Event table
BEGIN_EVENT_TABLE(VideoContext, wxEvtHandler) BEGIN_EVENT_TABLE(VideoContext, wxEvtHandler)
EVT_TIMER(VIDEO_PLAY_TIMER,VideoContext::OnPlayTimer) EVT_TIMER(VIDEO_PLAY_TIMER,VideoContext::OnPlayTimer)
END_EVENT_TABLE() END_EVENT_TABLE()
/// DOCME
VideoContext *VideoContext::instance = NULL;
/// @brief Constructor /// @brief Constructor
/// ///
VideoContext::VideoContext() VideoContext::VideoContext()
: ownGlContext(false) : ownGlContext(false)
, glContext(NULL) , glContext(NULL)
, provider(NULL)
, subsProvider(NULL)
, keyFramesLoaded(false)
, overKeyFramesLoaded(false)
, startFrame(-1) , startFrame(-1)
, endFrame(-1) , endFrame(-1)
, playNextFrame(-1) , playNextFrame(-1)
, nextFrame(-1) , nextFrame(-1)
, loaded(false)
, isPlaying(false) , isPlaying(false)
, keepAudioSync(true) , keepAudioSync(true)
, w(-1)
, h(-1)
, frame_n(0) , frame_n(0)
, length(0) , length(0)
, fps(0)
, arValue(1.) , arValue(1.)
, arType(0) , arType(0)
, hasSubtitles(false) , hasSubtitles(false)
, playAudioOnStep(OPT_GET("Audio/Plays When Stepping Video")) , playAudioOnStep(OPT_GET("Audio/Plays When Stepping Video"))
, grid(NULL) , grid(NULL)
, curLine(NULL)
, audio(NULL) , audio(NULL)
, VFR_Input(videoFPS)
, VFR_Output(ovrFPS)
{ {
} }
/// @brief Destructor
///
VideoContext::~VideoContext () { VideoContext::~VideoContext () {
Reset(); if (audio && audio->temporary) {
delete audio->provider;
delete audio->player;
}
tempFrame.Clear();
if (ownGlContext) if (ownGlContext)
delete glContext; delete glContext;
glContext = NULL;
} }
/// @brief Get Instance
/// @return
///
VideoContext *VideoContext::Get() { VideoContext *VideoContext::Get() {
if (!instance) { static VideoContext instance;
instance = new VideoContext; return &instance;
}
return instance;
} }
/// @brief Clear
///
void VideoContext::Clear() {
instance->audio = NULL;
delete instance;
instance = NULL;
}
/// @brief Reset
///
void VideoContext::Reset() { void VideoContext::Reset() {
loaded = false; StandardPaths::SetPathValue(_T("?video"), "");
StandardPaths::SetPathValue(_T("?video"),_T(""));
KeyFrames.Clear(); keyFrames.clear();
keyFramesLoaded = false; videoFPS = agi::vfr::Framerate();
// Remove temporary audio provider // Remove temporary audio provider
if (audio && audio->temporary) { if (audio && audio->temporary) {
@ -175,52 +141,25 @@ void VideoContext::Reset() {
// Remove video data // Remove video data
frame_n = 0; frame_n = 0;
length = 0; length = 0;
fps = 0;
keyFramesLoaded = false;
overKeyFramesLoaded = false;
isPlaying = false; isPlaying = false;
nextFrame = -1; nextFrame = -1;
curLine = NULL;
// Update displays
UpdateDisplays(true); UpdateDisplays(true);
// Clean up video data // Clean up video data
wxRemoveFile(tempfile); videoName.clear();
tempfile = _T("");
videoName = _T("");
tempFrame.Clear(); tempFrame.Clear();
// Remove provider // Remove provider
if (provider) { provider.reset();
delete provider; subsProvider.reset();
provider = NULL;
}
delete subsProvider;
subsProvider = NULL;
} }
/// @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) { void VideoContext::SetVideo(const wxString &filename) {
// Unload video Stop();
Reset(); Reset();
if (filename.empty()) return;
// Load video
if (!filename.IsEmpty()) {
try { try {
grid->CommitChanges(true); grid->CommitChanges(true);
@ -228,48 +167,29 @@ void VideoContext::SetVideo(const wxString &filename) {
GetGLContext(displayList.front())->SetCurrent(*displayList.front()); GetGLContext(displayList.front())->SetCurrent(*displayList.front());
// Choose a provider // Choose a provider
provider = VideoProviderFactoryManager::GetProvider(filename); provider.reset(VideoProviderFactoryManager::GetProvider(filename));
loaded = provider != NULL;
// Get subtitles provider // Get subtitles provider
try { try {
subsProvider = SubtitlesProviderFactoryManager::GetProvider(); subsProvider.reset(SubtitlesProviderFactoryManager::GetProvider());
} }
catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider")); } 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")); } catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider")); }
KeyFrames.Clear(); keyFrames = provider->GetKeyFrames();
// load keyframes if available
if (provider->AreKeyFramesLoaded()) {
KeyFrames = provider->GetKeyFrames();
keyFramesLoaded = true;
}
else {
keyFramesLoaded = false;
}
// Set frame rate // Set frame rate
fps = provider->GetFPS(); videoFPS = provider->GetFPS();
// does this provider need special vfr treatment? if (ovrFPS.IsLoaded()) {
if (provider->NeedsVFRHack()) { 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);
// FIXME: if (ovr == wxYES) {
// Unfortunately, this hack does not actually work for the one ovrFPS = agi::vfr::Framerate();
// provider that needs it (Avisynth). Go figure. ovrTimecodeFile.clear();
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 // Gather video parameters
length = provider->GetFrameCount(); length = provider->GetFrameCount();
w = provider->GetWidth();
h = provider->GetHeight();
// Set filename // Set filename
videoName = filename; videoName = filename;
@ -281,8 +201,8 @@ void VideoContext::SetVideo(const wxString &filename) {
frame_n = 0; frame_n = 0;
// Show warning // Show warning
wxString warning = provider->GetWarning().c_str(); wxString warning = provider->GetWarning();
if (!warning.IsEmpty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK); if (!warning.empty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK);
hasSubtitles = false; hasSubtitles = false;
if (filename.Right(4).Lower() == L".mkv") { if (filename.Right(4).Lower() == L".mkv") {
@ -295,13 +215,8 @@ void VideoContext::SetVideo(const wxString &filename) {
catch (wxString &e) { catch (wxString &e) {
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK); wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
} }
}
} }
/// @brief Add new display
/// @param display
/// @return
///
void VideoContext::AddDisplay(VideoDisplay *display) { void VideoContext::AddDisplay(VideoDisplay *display) {
for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) { for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
if ((*cur) == display) return; if ((*cur) == display) return;
@ -309,15 +224,12 @@ void VideoContext::AddDisplay(VideoDisplay *display) {
displayList.push_back(display); displayList.push_back(display);
} }
/// @brief Remove display
/// @param display
///
void VideoContext::RemoveDisplay(VideoDisplay *display) { void VideoContext::RemoveDisplay(VideoDisplay *display) {
displayList.remove(display); displayList.remove(display);
} }
void VideoContext::UpdateDisplays(bool full, bool seek) { 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++) { for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
VideoDisplay *display = *cur; VideoDisplay *display = *cur;
@ -343,9 +255,8 @@ void VideoContext::UpdateDisplays(bool full, bool seek) {
} }
} }
/// @brief Refresh subtitles
void VideoContext::Refresh () { void VideoContext::Refresh () {
if (subsProvider) { if (subsProvider.get()) {
AssExporter exporter(grid->ass); AssExporter exporter(grid->ass);
exporter.AddAutoFilters(); exporter.AddAutoFilters();
try { try {
@ -358,12 +269,8 @@ void VideoContext::Refresh () {
UpdateDisplays(false); UpdateDisplays(false);
} }
/// @brief Jumps to a frame and update display
/// @param n
/// @return
///
void VideoContext::JumpToFrame(int n) { void VideoContext::JumpToFrame(int n) {
if (!loaded) return; if (!IsLoaded()) return;
// Prevent intervention during playback // Prevent intervention during playback
if (isPlaying && n != playNextFrame) return; if (isPlaying && n != playNextFrame) return;
@ -372,30 +279,14 @@ void VideoContext::JumpToFrame(int n) {
UpdateDisplays(false, true); UpdateDisplays(false, true);
// Update grid
static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame"); static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
if (!isPlaying && highlight->GetBool()) grid->Refresh(false); if (!isPlaying && highlight->GetBool()) grid->Refresh(false);
} }
void VideoContext::JumpToTime(int ms, agi::vfr::Time end) {
JumpToFrame(FrameAtTime(ms, end));
/// @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);
} }
/// @brief Get GL context
/// @param canvas
/// @return
///
wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) { wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) {
if (!glContext) { if (!glContext) {
glContext = new wxGLContext(canvas); glContext = new wxGLContext(canvas);
@ -404,25 +295,17 @@ wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) {
return glContext; return glContext;
} }
/// @brief Requests a new frame
/// @param n
/// @param raw
/// @return
///
AegiVideoFrame VideoContext::GetFrame(int n,bool raw) { AegiVideoFrame VideoContext::GetFrame(int n,bool raw) {
// Current frame if -1 // Current frame if -1
if (n == -1) n = frame_n; if (n == -1) n = frame_n;
// Get frame
AegiVideoFrame frame = provider->GetFrame(n); AegiVideoFrame frame = provider->GetFrame(n);
// Raster subtitles if available/necessary // Raster subtitles if available/necessary
if (!raw && subsProvider) { if (!raw && subsProvider.get()) {
tempFrame.CopyFrom(frame); tempFrame.CopyFrom(frame);
try { try {
subsProvider->DrawSubtitles(tempFrame,VFR_Input.GetTimeAtFrame(n,true,true)/1000.0); subsProvider->DrawSubtitles(tempFrame,videoFPS.TimeAtFrame(n)/1000.0);
} }
catch (...) { catch (...) {
wxLogError(L"Subtitle rendering for the current frame failed.\n"); wxLogError(L"Subtitle rendering for the current frame failed.\n");
@ -434,9 +317,13 @@ AegiVideoFrame VideoContext::GetFrame(int n,bool raw) {
else return frame; else return frame;
} }
/// @brief Save snapshot int VideoContext::GetWidth() const {
/// @param raw return provider->GetWidth();
/// }
int VideoContext::GetHeight() const {
return provider->GetHeight();
}
void VideoContext::SaveSnapshot(bool raw) { void VideoContext::SaveSnapshot(bool raw) {
// Get folder // Get folder
static agi::OptionValue* ssPath = OPT_GET("Path/Screenshot"); static agi::OptionValue* ssPath = OPT_GET("Path/Screenshot");
@ -452,7 +339,7 @@ void VideoContext::SaveSnapshot(bool raw) {
} }
// Find out where the ?specifier points to // Find out where the ?specifier points to
basepath = StandardPaths::DecodePath(option); 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("/"))) { if ((basepath == _T("\\")) || (basepath == _T("/"))) {
// So save to the current user's home dir instead // So save to the current user's home dir instead
basepath = wxGetHomeDir(); basepath = wxGetHomeDir();
@ -472,21 +359,13 @@ void VideoContext::SaveSnapshot(bool raw) {
if (!tryPath.FileExists()) break; if (!tryPath.FileExists()) break;
} }
// Save
GetFrame(frame_n,raw).GetImage().SaveFile(path,wxBITMAP_TYPE_PNG); 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) { void VideoContext::GetScriptSize(int &sw,int &sh) {
grid->ass->GetResolution(sw,sh); grid->ass->GetResolution(sw,sh);
} }
/// @brief Play the next frame, possibly with audio
/// @return
///
void VideoContext::PlayNextFrame() { void VideoContext::PlayNextFrame() {
if (isPlaying) if (isPlaying)
return; return;
@ -495,12 +374,9 @@ void VideoContext::PlayNextFrame() {
JumpToFrame(frame_n + 1); JumpToFrame(frame_n + 1);
// Start playing audio // Start playing audio
if (playAudioOnStep->GetBool()) 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() { void VideoContext::PlayPrevFrame() {
if (isPlaying) if (isPlaying)
return; return;
@ -509,14 +385,10 @@ void VideoContext::PlayPrevFrame() {
JumpToFrame(frame_n -1); JumpToFrame(frame_n -1);
// Start playing audio // Start playing audio
if (playAudioOnStep->GetBool()) 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() { void VideoContext::Play() {
// Stop if already playing
if (isPlaying) { if (isPlaying) {
Stop(); Stop();
return; return;
@ -527,7 +399,7 @@ void VideoContext::Play() {
endFrame = -1; endFrame = -1;
// Start playing audio // 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. //audio->Play will override this if we put it before, so put it after.
isPlaying = true; isPlaying = true;
@ -538,14 +410,7 @@ void VideoContext::Play() {
playback.Start(10); playback.Start(10);
} }
/// @brief Play line
/// @return
///
void VideoContext::PlayLine() { void VideoContext::PlayLine() {
// Get line
AssDialogue *curline = grid->GetActiveLine(); AssDialogue *curline = grid->GetActiveLine();
if (!curline) return; if (!curline) return;
@ -554,8 +419,8 @@ void VideoContext::PlayLine() {
// Set variables // Set variables
isPlaying = true; isPlaying = true;
startFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true); startFrame = FrameAtTime(curline->Start.GetMS(),agi::vfr::START);
endFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false); endFrame = FrameAtTime(curline->End.GetMS(),agi::vfr::END);
// Jump to start // Jump to start
playNextFrame = startFrame; playNextFrame = startFrame;
@ -569,8 +434,6 @@ void VideoContext::PlayLine() {
playback.Start(10); playback.Start(10);
} }
/// @brief Stop
///
void VideoContext::Stop() { void VideoContext::Stop() {
if (isPlaying) { if (isPlaying) {
playback.Stop(); playback.Stop();
@ -579,10 +442,6 @@ void VideoContext::Stop() {
} }
} }
/// @brief Play timer
/// @param event
/// @return
///
void VideoContext::OnPlayTimer(wxTimerEvent &event) { void VideoContext::OnPlayTimer(wxTimerEvent &event) {
// Lock // Lock
wxMutexError res = playMutex.TryLock(); wxMutexError res = playMutex.TryLock();
@ -594,12 +453,12 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) {
int dif = playTime.Time(); int dif = playTime.Time();
// Find next frame // Find next frame
int startMs = VFR_Output.GetTimeAtFrame(startFrame); int startMs = TimeAtFrame(startFrame);
int nextFrame = frame_n; int nextFrame = frame_n;
int i=0; int i=0;
for (i=0;i<10;i++) { for (i=0;i<10;i++) {
if (nextFrame >= length) break; if (nextFrame >= length) break;
if (dif < VFR_Output.GetTimeAtFrame(nextFrame) - startMs) { if (dif < TimeAtFrame(nextFrame) - startMs) {
break; break;
} }
nextFrame++; nextFrame++;
@ -615,7 +474,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) {
if (nextFrame == frame_n) return; if (nextFrame == frame_n) return;
// Next frame is before or over 2 frames ahead, so force audio resync // 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 // Jump to next frame
playNextFrame = nextFrame; playNextFrame = nextFrame;
@ -624,7 +483,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) {
// Sync audio // Sync audio
if (keepAudioSync && nextFrame % 10 == 0 && audio && audio->provider && audio->player) { 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(); int64_t curPos = audio->player->GetCurrentPosition();
int delta = int(audPos-curPos); int delta = int(audPos-curPos);
if (delta < 0) delta = -delta; if (delta < 0) delta = -delta;
@ -633,67 +492,7 @@ void VideoContext::OnPlayTimer(wxTimerEvent &event) {
} }
} }
/// @brief Get name of temp work file double VideoContext::GetARFromType(int type) const {
/// @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) {
if (type == 0) return (double)VideoContext::Get()->GetWidth()/(double)VideoContext::Get()->GetHeight(); if (type == 0) return (double)VideoContext::Get()->GetWidth()/(double)VideoContext::Get()->GetHeight();
if (type == 1) return 4.0/3.0; if (type == 1) return 4.0/3.0;
if (type == 2) return 16.0/9.0; if (type == 2) return 16.0/9.0;
@ -701,18 +500,77 @@ double VideoContext::GetARFromType(int type) {
return 1.0; //error return 1.0; //error
} }
/// @brief Sets aspect ratio void VideoContext::SetAspectRatio(int type, double value) {
/// @param _type if (type != 4) value = GetARFromType(type);
/// @param value
///
void VideoContext::SetAspectRatio(int _type, double value) {
// Get value
if (_type != 4) value = GetARFromType(_type);
if (value < 0.5) value = 0.5; if (value < 0.5) value = 0.5;
if (value > 5.0) value = 5.0; if (value > 5.0) value = 5.0;
// Set arType = type;
arType = _type;
arValue = value; arValue = value;
UpdateDisplays(true); 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 <time.h>
#include <list> #include <list>
#include <memory>
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
#include <wx/timer.h> #include <wx/timer.h>
@ -56,12 +57,14 @@
#include <GL/glu.h> #include <GL/glu.h>
#endif #endif
#include <libaegisub/vfr.h>
#include "video_frame.h" #include "video_frame.h"
class SubtitlesGrid; class SubtitlesGrid;
class AudioProvider; class AudioProvider;
class AudioDisplay; class AudioDisplay;
class AssDialogue; class AssDialogue;
class KeyFrameFile;
class SubtitlesProvider; class SubtitlesProvider;
class VideoProvider; class VideoProvider;
class VideoDisplay; class VideoDisplay;
@ -77,11 +80,9 @@ namespace agi {
/// DOCME /// DOCME
class VideoContext : public wxEvtHandler { class VideoContext : public wxEvtHandler {
friend class AudioProvider; friend class AudioProvider;
friend class KeyFrameFile;
private: private:
/// DOCME
static VideoContext *instance;
/// DOCME /// DOCME
std::list<VideoDisplay*> displayList; std::list<VideoDisplay*> displayList;
@ -94,27 +95,14 @@ private:
/// DOCME /// DOCME
AegiVideoFrame tempFrame; AegiVideoFrame tempFrame;
/// DOCME
std::auto_ptr<VideoProvider> provider;
/// DOCME /// DOCME
wxString tempfile; std::auto_ptr<SubtitlesProvider> subsProvider;
/// DOCME /// DOCME
VideoProvider *provider; std::vector<int> keyFrames;
/// DOCME
SubtitlesProvider *subsProvider;
/// DOCME
bool keyFramesLoaded;
/// DOCME
bool overKeyFramesLoaded;
/// DOCME
wxArrayInt KeyFrames;
/// DOCME
wxArrayInt overKeyFrames;
/// DOCME /// DOCME
wxString keyFramesFilename; wxString keyFramesFilename;
@ -140,29 +128,18 @@ private:
/// DOCME /// DOCME
int nextFrame; int nextFrame;
/// DOCME
bool loaded;
/// DOCME /// DOCME
bool isPlaying; bool isPlaying;
/// DOCME /// DOCME
bool keepAudioSync; bool keepAudioSync;
/// DOCME
/// DOCME
int w,h;
/// DOCME /// DOCME
int frame_n; int frame_n;
/// DOCME /// DOCME
int length; int length;
/// DOCME
double fps;
/// DOCME /// DOCME
double arValue; double arValue;
@ -171,24 +148,28 @@ private:
bool hasSubtitles; bool hasSubtitles;
wxString ovrTimecodeFile;
agi::OptionValue* playAudioOnStep; agi::OptionValue* playAudioOnStep;
void OnPlayTimer(wxTimerEvent &event); void OnPlayTimer(wxTimerEvent &event);
agi::vfr::Framerate videoFPS;
agi::vfr::Framerate ovrFPS;
public: public:
/// DOCME /// DOCME
SubtitlesGrid *grid; SubtitlesGrid *grid;
/// DOCME /// File name of currently open video, if any
wxString videoName; wxString videoName;
/// DOCME
AssDialogue *curLine;
/// DOCME /// DOCME
AudioDisplay *audio; AudioDisplay *audio;
const agi::vfr::Framerate &VFR_Input;
const agi::vfr::Framerate &VFR_Output;
VideoContext(); VideoContext();
~VideoContext(); ~VideoContext();
@ -196,110 +177,114 @@ public:
void RemoveDisplay(VideoDisplay *display); void RemoveDisplay(VideoDisplay *display);
/// @brief DOCME /// @brief Get the video provider used for the currently open video
/// @return VideoProvider *GetProvider() const { return provider.get(); }
///
VideoProvider *GetProvider() { return provider; }
AegiVideoFrame GetFrame(int n,bool raw=false); 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); void SaveSnapshot(bool raw);
wxGLContext *GetGLContext(wxGLCanvas *canvas); wxGLContext *GetGLContext(wxGLCanvas *canvas);
/// @brief DOCME /// @brief Is there a video loaded?
/// @return bool IsLoaded() const { return !!provider.get(); }
bool IsLoaded() { return loaded; }
/// @brief DOCME /// @brief Is the video currently playing?
/// @return bool IsPlaying() const { return isPlaying; }
bool IsPlaying() { return isPlaying; }
/// @brief Does the video file loaded have muxed subtitles that we can load? /// @brief Does the video file loaded have muxed subtitles that we can load?
bool HasSubtitles() {return hasSubtitles; } bool HasSubtitles() const { return hasSubtitles; }
/// @brief DOCME /// @brief DOCME
/// @param sync /// @param sync
/// @return /// @return
void EnableAudioSync(bool sync = true) { keepAudioSync = sync; } void EnableAudioSync(bool sync = true) { keepAudioSync = sync; }
/// @brief Get the width of the currently open video
int GetWidth() const;
/// @brief DOCME /// @brief Get the height of the currently open video
/// @return int GetHeight() const;
int GetWidth() { return w; }
/// @brief DOCME /// @brief Get the length in frames of the currently open video
/// @return int GetLength() const { return length; }
int GetHeight() { return h; }
/// @brief DOCME /// @brief Get the current frame number
/// @return int GetFrameN() const { return frame_n; }
int GetLength() { return length; }
/// @brief DOCME double GetARFromType(int type) const;
/// @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);
void SetAspectRatio(int type,double value=1.0); void SetAspectRatio(int type,double value=1.0);
/// @brief DOCME /// @brief DOCME
/// @return /// @return
int GetAspectRatioType() { return arType; } int GetAspectRatioType() const { return arType; }
/// @brief DOCME /// @brief DOCME
/// @return /// @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); void SetVideo(const wxString &filename);
/// @brief Close the video, keyframes and timecodes
void Reset(); void Reset();
void Reload();
/// @brief Jump to the beginning of a frame
/// @param n Frame number to jump to
void JumpToFrame(int n); 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(); void Refresh();
/// @brief Update the video display /// @brief Update the video display
/// @param full Recalculate size and slider lengths /// @param full Recalculate size and slider lengths
/// @param seek Update is just a seek and file has not changed /// @param seek Update is just a seek and file has not changed
void UpdateDisplays(bool full, bool seek = false); 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); void GetScriptSize(int &w,int &h);
wxString GetTempWorkFile ();
/// Starting playing the video
void Play(); void Play();
/// Play the next frame then stop
void PlayNextFrame(); void PlayNextFrame();
/// Play the previous frame then stop
void PlayPrevFrame(); void PlayPrevFrame();
/// Seek to the beginning of the current line, then play to the end of it
void PlayLine(); void PlayLine();
/// Stop playing
void Stop(); void Stop();
wxArrayInt GetKeyFrames(); const std::vector<int>& GetKeyFrames() const { return keyFrames; };
void SetKeyFrames(wxArrayInt frames); wxString GetKeyFramesName() const { return keyFramesFilename; }
void SetOverKeyFrames(wxArrayInt frames); void LoadKeyframes(wxString filename);
void CloseOverKeyFrames(); void SaveKeyframes(wxString filename);
bool OverKeyFramesLoaded(); void CloseKeyframes();
bool KeyFramesLoaded(); bool OverKeyFramesLoaded() const { return !keyFramesFilename.empty(); }
bool KeyFramesLoaded() const { return !keyFrames.empty(); }
/// @brief DOCME wxString GetTimecodesName() const { return ovrTimecodeFile; }
/// @return void LoadTimecodes(wxString filename);
/// void SaveTimecodes(wxString filename);
wxString GetKeyFramesName() { return keyFramesFilename; } void CloseTimecodes();
bool OverTimecodesLoaded() const { return ovrFPS.IsLoaded(); }
bool TimecodesLoaded() const { return videoFPS.IsLoaded() || ovrFPS.IsLoaded(); };
/// @brief DOCME const agi::vfr::Framerate& FPS() const { return ovrFPS.IsLoaded() ? ovrFPS : videoFPS; }
/// @param name
/// int TimeAtFrame(int frame, agi::vfr::Time type = agi::vfr::EXACT) const;
void SetKeyFramesName(wxString name) { keyFramesFilename = name; } int FrameAtTime(int time, agi::vfr::Time type = agi::vfr::EXACT) const;
static VideoContext *Get(); static VideoContext *Get();
static void Clear();
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@ -60,8 +60,8 @@
#include "hotkeys.h" #include "hotkeys.h"
#include "options.h" #include "options.h"
#include "main.h" #include "main.h"
#include "subs_grid.h"
#include "video_out_gl.h" #include "video_out_gl.h"
#include "vfr.h"
#include "video_box.h" #include "video_box.h"
#include "video_context.h" #include "video_context.h"
#include "video_slider.h" #include "video_slider.h"
@ -166,7 +166,7 @@ void VideoDisplay::SetFrame(int frameNumber) {
// Get time for frame // 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 h = time / 3600000;
int m = time % 3600000 / 60000; int m = time % 3600000 / 60000;
int s = time % 60000 / 1000; int s = time % 60000 / 1000;
@ -174,7 +174,7 @@ void VideoDisplay::SetFrame(int frameNumber) {
// Set the text box for frame number and time // Set the text box for frame number and time
PositionDisplay->SetValue(wxString::Format(L"%01i:%02i:%02i.%03i - %i", h, m, s, ms, frameNumber)); 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 // Set the background color to indicate this is a keyframe
PositionDisplay->SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColour())); PositionDisplay->SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColour()));
PositionDisplay->SetForegroundColour(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/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 startOff = 0;
int endOff = 0; int endOff = 0;
if (AssDialogue *curLine = context->curLine) { if (AssDialogue *curLine = context->grid->GetActiveLine()) {
startOff = time - curLine->Start.GetMS(); startOff = time - curLine->Start.GetMS();
endOff = time - curLine->End.GetMS(); endOff = time - curLine->End.GetMS();
} }

View File

@ -50,7 +50,6 @@
#include "mkv_wrap.h" #include "mkv_wrap.h"
#include "options.h" #include "options.h"
#include "standard_paths.h" #include "standard_paths.h"
#include "vfr.h"
#include "vfw_wrap.h" #include "vfw_wrap.h"
#include "video_context.h" #include "video_context.h"
#include "video_provider_avs.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)); AVSTRACE(wxString::Format(_T("AvisynthVideoProvider: Creating new AvisynthVideoProvider: \"%s\", \"%s\""), _filename, _subfilename));
bool mpeg2dec3_priority = true; bool mpeg2dec3_priority = true;
RGB32Video = NULL; RGB32Video = NULL;
fps = 0;
num_frames = 0; num_frames = 0;
last_fnum = -1; last_fnum = -1;
byFrame = false; KeyFrames.clear();
KeyFrames.Clear();
keyFramesLoaded = false;
isVfr = false;
AVSTRACE(_T("AvisynthVideoProvider: Opening video")); AVSTRACE(_T("AvisynthVideoProvider: Opening video"));
RGB32Video = OpenVideo(_filename,mpeg2dec3_priority); RGB32Video = OpenVideo(_filename,mpeg2dec3_priority);
@ -92,12 +87,6 @@ AvisynthVideoProvider::~AvisynthVideoProvider() {
AVSTRACE(_T("AvisynthVideoProvider: AvisynthVideoProvider destroyed")); AVSTRACE(_T("AvisynthVideoProvider: AvisynthVideoProvider destroyed"));
} }
////////////////////////////////////// VIDEO PROVIDER //////////////////////////////////////
/// @brief Actually open the video into Avisynth /// @brief Actually open the video into Avisynth
/// @param _filename /// @param _filename
/// @param mpeg2dec3_priority /// @param mpeg2dec3_priority
@ -109,7 +98,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Got AVS mutex")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Got AVS mutex"));
AVSValue script; AVSValue script;
byFrame = false;
usedDirectShow = false; usedDirectShow = false;
decoderName = _("Unknown"); decoderName = _("Unknown");
@ -138,7 +126,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
AVSValue args[2] = { videoFilename, false }; AVSValue args[2] = { videoFilename, false };
script = env->Invoke("AviSource", AVSValue(args,2), argnames); script = env->Invoke("AviSource", AVSValue(args,2), argnames);
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio"));
byFrame = true;
decoderName = _T("AviSource"); decoderName = _T("AviSource");
} }
@ -253,30 +240,16 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
} }
// Read keyframes and timecodes from MKV file // Read keyframes and timecodes from MKV file
isVfr = false;
FrameRate temp;
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen(); bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
KeyFrames.Clear(); KeyFrames.clear();
if (extension == _T(".mkv") || mkvOpen) { if (extension == _T(".mkv") || mkvOpen) {
// Parse mkv // Parse mkv
if (!mkvOpen) MatroskaWrapper::wrapper.Open(_filename); if (!mkvOpen) MatroskaWrapper::wrapper.Open(_filename);
// Get keyframes // Get keyframes
KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames(); KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames();
keyFramesLoaded = true;
// Ask to override timecodes MatroskaWrapper::wrapper.SetToTimecodes(vfr_fps);
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;
}
}
// Close mkv // Close mkv
MatroskaWrapper::wrapper.Close(); 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 // check if we have windows, if so we can load keyframes from AVI files using VFW
#ifdef __WINDOWS__ #ifdef __WINDOWS__
else if (extension == _T(".avi")) { else if (extension == _T(".avi")) {
keyFramesLoaded = false; KeyFrames.clear();
KeyFrames.Clear();
KeyFrames = VFWWrapper::GetKeyFrames(_filename); KeyFrames = VFWWrapper::GetKeyFrames(_filename);
keyFramesLoaded = true;
} }
#endif /* __WINDOWS__ */ #endif /* __WINDOWS__ */
// Check if the file is all keyframes // Check if the file is all keyframes
bool isAllKeyFrames = true; 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? // Is the last keyframe not this keyframe -1?
if (KeyFrames[i-1] != (int)(i-1)) { if (KeyFrames[i-1] != (int)(i-1)) {
// It's not all keyframes, go ahead // 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 it is all keyframes, discard the keyframe info as it is useless
if (isAllKeyFrames) { if (isAllKeyFrames) {
KeyFrames.Clear(); KeyFrames.clear();
keyFramesLoaded = false;
} }
real_fps = (double)vi.fps_numerator / vi.fps_denominator;
// Convert to RGB32 // Convert to RGB32
script = env->Invoke("ConvertToRGB32", script); script = env->Invoke("ConvertToRGB32", script);
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Converted to RGB32")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Converted to RGB32"));
@ -323,17 +295,10 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
/// @param _n /// @param _n
/// @return /// @return
/// ///
const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n) { const AegiVideoFrame AvisynthVideoProvider::GetFrame(int n) {
// Transform n if overriden if (vfr_fps.IsLoaded()) {
int n = _n; n = real_fps.FrameAtTime(vfr_fps.TimeAtFrame(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;
} }
// Get avs frame // Get avs frame
AVSTRACE(_T("AvisynthVideoProvider::GetFrame")); AVSTRACE(_T("AvisynthVideoProvider::GetFrame"));
wxMutexLocker lock(AviSynthMutex); wxMutexLocker lock(AviSynthMutex);
@ -362,24 +327,11 @@ const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n) {
return final; return final;
} }
/// @brief Override frame times
/// @param list
///
void AvisynthVideoProvider::OverrideFrameTimeList(wxArrayInt list) {
frameTime = list;
num_frames = frameTime.Count();
}
/// @brief Get warning /// @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!"; 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""; else return L"";
} }
#endif #endif

View File

@ -34,22 +34,16 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#ifdef WITH_AVISYNTH #ifdef WITH_AVISYNTH
#include "avisynth_wrap.h" #include "avisynth_wrap.h"
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
/// DOCME /// DOCME
/// @class AvisynthVideoProvider /// @class AvisynthVideoProvider
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class AvisynthVideoProvider: public VideoProvider, AviSynthWrapper { class AvisynthVideoProvider: public VideoProvider, AviSynthWrapper {
private:
/// DOCME /// DOCME
VideoInfo vi; VideoInfo vi;
@ -75,27 +69,11 @@ private:
/// DOCME /// DOCME
double fps; agi::vfr::Framerate real_fps;
agi::vfr::Framerate vfr_fps;
/// DOCME /// DOCME
wxArrayInt frameTime; std::vector<int> KeyFrames;
/// DOCME
bool byFrame;
/// DOCME
wxArrayInt KeyFrames;
/// DOCME
bool keyFramesLoaded;
/// DOCME
bool isVfr;
/// DOCME
FrameRate trueFrameRate;
/// DOCME /// DOCME
PClip RGB32Video; PClip RGB32Video;
@ -108,72 +86,16 @@ public:
const AegiVideoFrame GetFrame(int n); const AegiVideoFrame GetFrame(int n);
/// @brief // properties int GetPosition() const { return last_fnum; };
/// @return 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 GetPosition() { return last_fnum; }; int GetWidth() const { return vi.width; };
int GetHeight() const { return vi.height; };
/// @brief DOCME std::vector<int> GetKeyFrames() const { return KeyFrames; };
/// @return wxString GetWarning() const;
/// wxString GetDecoderName() const { return wxString(L"Avisynth/") + decoderName; }
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; }
}; };
/// DOCME /// DOCME
/// @class AvisynthVideoProviderFactory /// @class AvisynthVideoProviderFactory
/// @brief DOCME /// @brief DOCME
@ -188,7 +110,4 @@ public:
VideoProvider *CreateProvider(wxString video) { return new AvisynthVideoProvider(video); } VideoProvider *CreateProvider(wxString video) { return new AvisynthVideoProvider(video); }
}; };
#endif #endif

View File

@ -34,39 +34,43 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "video_provider_cache.h" #include "video_provider_cache.h"
/// DOCME
/// @class CachedFrame
/// @brief DOCME
///
/// DOCME
struct CachedFrame {
/// DOCME
AegiVideoFrame frame;
/// DOCME
int n;
};
/// @brief Constructor /// @brief Constructor
/// @param parent /// @param parent
/// ///
VideoProviderCache::VideoProviderCache(VideoProvider *parent) { VideoProviderCache::VideoProviderCache(VideoProvider *parent)
master = parent; : master(parent)
cacheMax = 0; , cacheMax(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
if (parent->WantsCaching()) {
cacheMax = OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20; // convert MB to bytes
else
cacheMax = 0;
} }
/// @brief Destructor /// @brief Destructor
/// ///
VideoProviderCache::~VideoProviderCache() { VideoProviderCache::~VideoProviderCache() {
delete master; while (cache.size()) {
ClearCache(); cache.front().frame.Clear();
cache.pop_front();
}
} }
/// @brief Get frame /// @brief Get frame
/// @param n /// @param n
/// @return /// @return
@ -88,21 +92,14 @@ const AegiVideoFrame VideoProviderCache::GetFrame(int n) {
const AegiVideoFrame *srcFrame = &frame; const AegiVideoFrame *srcFrame = &frame;
// Cache frame // Cache frame
pos = n;
Cache(n,*srcFrame); Cache(n,*srcFrame);
return *srcFrame; return *srcFrame;
} }
/// @brief Add to cache /// @brief Add to cache
/// @param n /// @param n
/// @param frame /// @param frame
/// @return
///
void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) { void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) {
// Cache enabled?
if (cacheMax == 0) return;
// Cache full, use frame at front // Cache full, use frame at front
if (GetCurCacheSize() >= cacheMax) { if (GetCurCacheSize() >= cacheMax) {
cache.push_back(cache.front()); cache.push_back(cache.front());
@ -119,17 +116,6 @@ void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) {
cache.back().frame.CopyFrom(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 /// @brief Get the current size of the cache
/// @return Returns the size in bytes /// @return Returns the size in bytes
unsigned VideoProviderCache::GetCurCacheSize() { unsigned VideoProviderCache::GetCurCacheSize() {
@ -138,103 +124,3 @@ unsigned VideoProviderCache::GetCurCacheSize() {
sz += i->frame.memSize; sz += i->frame.memSize;
return sz; 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 /// @ingroup video_input
/// ///
//////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <list> #include <list>
#include <memory>
#endif #endif
#include "include/aegisub/video_provider.h" #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 /// DOCME
/// @class VideoProviderCache /// @class VideoProviderCache
@ -69,10 +49,8 @@ public:
/// ///
/// DOCME /// DOCME
class VideoProviderCache : public VideoProvider { class VideoProviderCache : public VideoProvider {
private:
/// DOCME /// DOCME
VideoProvider *master; std::auto_ptr<VideoProvider> master;
/// DOCME /// DOCME
unsigned int cacheMax; unsigned int cacheMax;
@ -80,16 +58,11 @@ private:
/// DOCME /// DOCME
std::list<CachedFrame> cache; std::list<CachedFrame> cache;
/// DOCME
int pos;
void Cache(int n,const AegiVideoFrame frame); void Cache(int n,const AegiVideoFrame frame);
AegiVideoFrame GetCachedFrame(int n); AegiVideoFrame GetCachedFrame(int n);
protected:
// Cache functions // Cache functions
unsigned GetCurCacheSize(); unsigned GetCurCacheSize();
void ClearCache();
public: public:
// Base methods // Base methods
@ -98,20 +71,14 @@ public:
virtual ~VideoProviderCache(); virtual ~VideoProviderCache();
// Override the following methods: // Override the following methods:
virtual int GetPosition(); // Get the number of the last frame loaded virtual int GetPosition() const { return master->GetPosition(); }
virtual int GetFrameCount(); // Get total number of frames virtual int GetFrameCount() const { return master->GetFrameCount(); }
virtual int GetWidth(); // Returns the video width in pixels virtual int GetWidth() const { return master->GetWidth(); }
virtual int GetHeight(); // Returns the video height in pixels virtual int GetHeight() const { return master->GetHeight(); }
virtual double GetFPS(); // Get framerate in frames per second virtual agi::vfr::Framerate GetFPS() const { return master->GetFPS(); }
virtual bool AreKeyFramesLoaded(); virtual std::vector<int> GetKeyFrames() const { return master->GetKeyFrames(); }
virtual bool IsVFR(); virtual wxString GetWarning() const { return master->GetWarning(); }
virtual wxArrayInt GetKeyFrames(); virtual wxString GetDecoderName() const { return master->GetDecoderName(); }
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();
}; };

View File

@ -34,9 +34,6 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -46,18 +43,6 @@
#include "colorspace.h" #include "colorspace.h"
#include "video_provider_dummy.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 /// @brief Constructor
/// @param _fps /// @param _fps
/// @param frames /// @param frames
@ -130,8 +115,6 @@ void DummyVideoProvider::Create(double _fps, int frames, int _width, int _height
} }
} }
/// @brief Parsing constructor /// @brief Parsing constructor
/// @param filename /// @param filename
/// ///
@ -194,8 +177,6 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
Create(fps, _frames, _width, _height, wxColour(red, green, blue), pattern); Create(fps, _frames, _width, _height, wxColour(red, green, blue), pattern);
} }
/// @brief Direct constructor /// @brief Direct constructor
/// @param _fps /// @param _fps
/// @param frames /// @param frames
@ -208,16 +189,12 @@ DummyVideoProvider::DummyVideoProvider(double _fps, int frames, int _width, int
Create(_fps, frames, _width, _height, colour, pattern); Create(_fps, frames, _width, _height, colour, pattern);
} }
/// @brief Destructor /// @brief Destructor
/// ///
DummyVideoProvider::~DummyVideoProvider() { DummyVideoProvider::~DummyVideoProvider() {
frame.Clear(); frame.Clear();
} }
/// @brief Construct a fake filename describing the video /// @brief Construct a fake filename describing the video
/// @param fps /// @param fps
/// @param frames /// @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("")); 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 /// @brief Get frame
/// @param n /// @param n
/// @return /// @return
@ -241,59 +216,3 @@ const AegiVideoFrame DummyVideoProvider::GetFrame(int n) {
lastFrame = n; lastFrame = n;
return frame; 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 // The dummy video provider needs a header, since it needs to be created directly as a special case
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#include <wx/colour.h> #include <wx/colour.h>
#endif #endif
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
#include "vfr.h"
/// DOCME /// DOCME
/// @class DummyVideoProvider /// @class DummyVideoProvider
@ -55,8 +48,6 @@
/// ///
/// DOCME /// DOCME
class DummyVideoProvider : public VideoProvider { class DummyVideoProvider : public VideoProvider {
private:
/// DOCME /// DOCME
int lastFrame; int lastFrame;
@ -64,7 +55,7 @@ private:
int framecount; int framecount;
/// DOCME /// DOCME
double fps; agi::vfr::Framerate fps;
/// DOCME /// DOCME
int width; int width;
@ -85,37 +76,11 @@ public:
const AegiVideoFrame GetFrame(int n); const AegiVideoFrame GetFrame(int n);
static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern); static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern);
int GetPosition(); int GetPosition() const { return lastFrame; }
int GetFrameCount(); int GetFrameCount() const { return framecount; }
int GetWidth() const { return width; }
int GetWidth(); int GetHeight() const { return height; }
int GetHeight(); agi::vfr::Framerate GetFPS() const { return fps; }
double GetFPS(); std::vector<int> GetKeyFrames() const { return std::vector<int>(); };
wxString GetDecoderName() const { return L"Dummy Video Provider"; }
/// @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();
}; };

View File

@ -38,8 +38,6 @@
#ifdef WITH_FFMPEGSOURCE #ifdef WITH_FFMPEGSOURCE
///////////
// Headers
#ifndef AGI_PRE #ifndef AGI_PRE
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <objbase.h> #include <objbase.h>
@ -79,7 +77,6 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
// clean up variables // clean up variables
VideoSource = NULL; VideoSource = NULL;
KeyFramesLoaded = false;
FrameNumber = -1; FrameNumber = -1;
ErrInfo.Buffer = FFMSErrMsg; ErrInfo.Buffer = FFMSErrMsg;
ErrInfo.BufferSize = sizeof(FFMSErrMsg); ErrInfo.BufferSize = sizeof(FFMSErrMsg);
@ -249,6 +246,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
const FFMS_FrameInfo *CurFrameData; const FFMS_FrameInfo *CurFrameData;
// build list of keyframes and timecodes // build list of keyframes and timecodes
std::vector<int> TimecodesVector;
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) { for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum); CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
if (CurFrameData == NULL) { if (CurFrameData == NULL) {
@ -258,47 +256,29 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
// keyframe? // keyframe?
if (CurFrameData->KeyFrame) if (CurFrameData->KeyFrame)
KeyFramesList.Add(CurFrameNum); KeyFramesList.push_back(CurFrameNum);
// calculate timestamp and add to timecodes vector // calculate timestamp and add to timecodes vector
int Timestamp = (int)((CurFrameData->PTS * TimeBase->Num) / TimeBase->Den); int Timestamp = (int)((CurFrameData->PTS * TimeBase->Num) / TimeBase->Den);
TimecodesVector.push_back(Timestamp); TimecodesVector.push_back(Timestamp);
} }
KeyFramesLoaded = true; Timecodes = agi::vfr::Framerate(TimecodesVector);
// 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);
}
FrameNumber = 0; FrameNumber = 0;
} }
/// @brief Close video /// @brief Close video
/// ///
void FFmpegSourceVideoProvider::Close() { void FFmpegSourceVideoProvider::Close() {
FFMS_DestroyVideoSource(VideoSource); FFMS_DestroyVideoSource(VideoSource);
VideoSource = NULL; VideoSource = NULL;
KeyFramesLoaded = false;
KeyFramesList.clear(); KeyFramesList.clear();
TimecodesVector.clear();
FrameNumber = -1; FrameNumber = -1;
Timecodes = agi::vfr::Framerate();
CurFrame.Clear(); CurFrame.Clear();
} }
/// @brief Get frame /// @brief Get frame
/// @param _n /// @param _n
/// @return /// @return
@ -323,48 +303,4 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32); CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32);
return CurFrame; 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 */ #endif /* WITH_FFMPEGSOURCE */

View File

@ -34,8 +34,6 @@
/// @ingroup video_input ffms /// @ingroup video_input ffms
/// ///
///////////
// Headers
#ifdef WITH_FFMPEGSOURCE #ifdef WITH_FFMPEGSOURCE
#ifndef AGI_PRE #ifndef AGI_PRE
#include <vector> #include <vector>
@ -43,7 +41,6 @@
#include "ffmpegsource_common.h" #include "ffmpegsource_common.h"
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
#include "vfr.h"
/// @class FFmpegSourceVideoProvider /// @class FFmpegSourceVideoProvider
@ -56,10 +53,8 @@ private:
int Width; /// width in pixels int Width; /// width in pixels
int Height; /// height in pixels int Height; /// height in pixels
int FrameNumber; /// current framenumber int FrameNumber; /// current framenumber
wxArrayInt KeyFramesList; /// list of keyframes std::vector<int> KeyFramesList; /// list of keyframes
bool KeyFramesLoaded; /// keyframe loading state agi::vfr::Framerate Timecodes; /// vfr object
std::vector<int> TimecodesVector; /// list of timestamps
FrameRate Timecodes; /// vfr object
bool COMInited; /// COM initialization state bool COMInited; /// COM initialization state
AegiVideoFrame CurFrame; /// current video frame AegiVideoFrame CurFrame; /// current video frame
@ -76,35 +71,22 @@ public:
~FFmpegSourceVideoProvider(); ~FFmpegSourceVideoProvider();
const AegiVideoFrame GetFrame(int n); const AegiVideoFrame GetFrame(int n);
int GetPosition();
int GetFrameCount();
int GetWidth(); int GetPosition() const { return FrameNumber; }
int GetHeight(); int GetFrameCount() const { return VideoInfo->NumFrames; }
double GetFPS(); 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 /// @brief Gets a list of keyframes
/// @return Returns a wxArrayInt of keyframes. /// @return Returns a wxArrayInt of keyframes.
wxArrayInt GetKeyFrames() { return KeyFramesList; }; std::vector<int> GetKeyFrames() const { return KeyFramesList; };
/// @brief Checks if source is VFR wxString GetDecoderName() const { return L"FFmpegSource"; }
/// @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"; }
/// @brief Gets the desired cache behavior. /// @brief Gets the desired cache behavior.
/// @return Returns true. /// @return Returns true.
bool WantsCaching() { return true; } bool WantsCaching() const { return true; }
}; };
/// @class FFmpegSourceVideoProviderFactory /// @class FFmpegSourceVideoProviderFactory
/// @brief Creates a FFmpegSource video provider. /// @brief Creates a FFmpegSource video provider.
class FFmpegSourceVideoProviderFactory : public VideoProviderFactory { class FFmpegSourceVideoProviderFactory : public VideoProviderFactory {
@ -115,7 +97,4 @@ public:
VideoProvider *CreateProvider(wxString video) { return new FFmpegSourceVideoProvider(video); } VideoProvider *CreateProvider(wxString video) { return new FFmpegSourceVideoProvider(video); }
}; };
#endif /* WITH_FFMPEGSOURCE */ #endif /* WITH_FFMPEGSOURCE */

View File

@ -34,9 +34,6 @@
/// @ingroup video_input /// @ingroup video_input
/// ///
///////////
// Headers
#include "config.h" #include "config.h"
#include <libaegisub/log.h> #include <libaegisub/log.h>
@ -44,7 +41,7 @@
#include "compat.h" #include "compat.h"
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "vfr.h"
#ifdef WITH_AVISYNTH #ifdef WITH_AVISYNTH
#include "video_provider_avs.h" #include "video_provider_avs.h"
#endif #endif

View File

@ -54,8 +54,6 @@
#define MacOffsetRect OffsetRect #define MacOffsetRect OffsetRect
#endif #endif
/// @brief DOCME /// @brief DOCME
/// @param filename /// @param filename
/// ///
@ -99,8 +97,6 @@ QuickTimeVideoProvider::QuickTimeVideoProvider(wxString filename) {
} }
} }
/// @brief DOCME /// @brief DOCME
/// ///
QuickTimeVideoProvider::~QuickTimeVideoProvider() { QuickTimeVideoProvider::~QuickTimeVideoProvider() {
@ -108,8 +104,6 @@ QuickTimeVideoProvider::~QuickTimeVideoProvider() {
DeInitQuickTime(); DeInitQuickTime();
} }
/// @brief DOCME /// @brief DOCME
/// ///
void QuickTimeVideoProvider::Close() { void QuickTimeVideoProvider::Close() {
@ -123,15 +117,10 @@ void QuickTimeVideoProvider::Close() {
DisposeHandle(in_dataref); DisposeHandle(in_dataref);
in_dataref = NULL; in_dataref = NULL;
keyframes.Clear(); keyframes.clear();
qt_timestamps.clear(); qt_timestamps.clear();
} }
/// @brief DOCME /// @brief DOCME
/// @param _filename /// @param _filename
/// ///
@ -175,28 +164,11 @@ void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
throw wxString(_T("QuickTime video provider: failed to index file")); throw wxString(_T("QuickTime video provider: failed to index file"));
// ask about vfr override etc // ask about vfr override etc
vfr_fps.SetVFR(timecodes); vfr_fps = agi::vfr::Framerate(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;
cur_fn = 0; cur_fn = 0;
} }
/// @brief DOCME /// @brief DOCME
/// @return /// @return
/// ///
@ -237,8 +209,6 @@ std::vector<int> QuickTimeVideoProvider::IndexFile() {
return timecodes; return timecodes;
} }
/// @brief DOCME /// @brief DOCME
/// @param n /// @param n
/// @return /// @return
@ -283,76 +253,4 @@ const AegiVideoFrame QuickTimeVideoProvider::GetFrame(int n) {
return dst_frame; 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 */ #endif /* WITH_QUICKTIME */

View File

@ -49,8 +49,6 @@
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
#include "vfr.h"
/// DOCME /// DOCME
/// @class QuickTimeVideoProvider /// @class QuickTimeVideoProvider
@ -58,47 +56,42 @@
/// ///
/// DOCME /// DOCME
class QuickTimeVideoProvider : public VideoProvider, QuickTimeProvider { class QuickTimeVideoProvider : public VideoProvider, QuickTimeProvider {
private: /// source object
Movie movie;
/// DOCME /// render buffer
Movie movie; // source object GWorldPtr gw;
/// DOCME /// input data handle
GWorldPtr gw; // render buffer Handle in_dataref;
/// DOCME
Handle in_dataref; // input data handle
/// DOCME /// DOCME
/// DOCME /// width/height
int w, h; // width/height int w, h;
/// DOCME /// length of file in frames
int num_frames; // length of file in frames int num_frames;
/// DOCME /// current frame number
int cur_fn; // current frame number int cur_fn;
/// DOCME /// vfr framerate
FrameRate vfr_fps; // vfr framerate Framerate vfr_fps;
/// DOCME /// list of keyframes
double assumed_fps; // average framerate std::vector<int> keyframes;
/// DOCME /// qt timestamps (used for seeking)
wxArrayInt keyframes; // list of keyframes std::vector<int> qt_timestamps;
/// DOCME
std::vector<int> qt_timestamps; // qt timestamps (used for seeking)
/// DOCME /// quicktime error code
OSErr qt_err; // quicktime error code OSErr qt_err;
/// DOCME /// aegisub error message
wxString errmsg; // aegisub error message wxString errmsg;
void LoadVideo(const wxString filename); void LoadVideo(const wxString filename);
std::vector<int> IndexFile(); std::vector<int> IndexFile();
@ -109,34 +102,18 @@ public:
~QuickTimeVideoProvider(); ~QuickTimeVideoProvider();
const AegiVideoFrame GetFrame(int n); const AegiVideoFrame GetFrame(int n);
int GetPosition();
int GetFrameCount();
int GetWidth(); int GetPosition() const { return cur_fn; }
int GetHeight(); int GetFrameCount() const { return num_frames; }
double GetFPS(); int GetWidth() const { return w; }
int GetHeight() const { return h; }
/// @brief DOCME agi::vfr::Framerate GetFPS() const { return vfr_fps; }
/// @return std::vector<int> GetKeyFrames() const { return keyframes; };
/// wxString GetDecoderName() const { return L"QuickTime"; };
bool IsVFR() { return true; }; bool WantsCaching() const { return true; };
FrameRate GetTrueFrameRate(); wxString GetWarning() const { return errmsg; }
wxArrayInt GetKeyFrames();
bool QuickTimeVideoProvider::AreKeyFramesLoaded();
/// @brief DOCME
/// @return
///
wxString GetDecoderName() { return L"QuickTime"; };
/// @brief DOCME
/// @return
///
bool WantsCaching() { return true; };
}; };
/// DOCME /// DOCME
/// @class QuickTimeVideoProviderFactory /// @class QuickTimeVideoProviderFactory
/// @brief DOCME /// @brief DOCME
@ -151,7 +128,4 @@ public:
VideoProvider *CreateProvider(wxString video) { return new QuickTimeVideoProvider(video); } VideoProvider *CreateProvider(wxString video) { return new QuickTimeVideoProvider(video); }
}; };
#endif /* WITH_QUICKTIME */ #endif /* WITH_QUICKTIME */

View File

@ -309,6 +309,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
fps_rat.den = t_fps_den; fps_rat.den = t_fps_den;
pixfmt = t_pixfmt != Y4M_PIXFMT_NONE ? t_pixfmt : Y4M_PIXFMT_420JPEG; pixfmt = t_pixfmt != Y4M_PIXFMT_NONE ? t_pixfmt : Y4M_PIXFMT_420JPEG;
imode = t_imode != Y4M_ILACE_NOTSET ? t_imode : Y4M_ILACE_UNKNOWN; imode = t_imode != Y4M_ILACE_NOTSET ? t_imode : Y4M_ILACE_UNKNOWN;
fps = double(fps_rat.num) / fps_rat.den;
inited = true; inited = true;
} }
} }
@ -430,27 +431,3 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
return dst_frame; 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 /// @ingroup video_input
/// ///
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
#ifndef AGI_PRE #ifndef AGI_PRE
#include <stdio.h> #include <stdio.h>
@ -46,16 +44,12 @@
#include <wx/log.h> #include <wx/log.h>
#endif #endif
/// the maximum allowed header length, in bytes /// the maximum allowed header length, in bytes
#define YUV4MPEG_HEADER_MAXLEN 128 #define YUV4MPEG_HEADER_MAXLEN 128
/// @class YUV4MPEGVideoProvider /// @class YUV4MPEGVideoProvider
/// @brief Implements reading of YUV4MPEG uncompressed video files /// @brief Implements reading of YUV4MPEG uncompressed video files
class YUV4MPEGVideoProvider : public VideoProvider { class YUV4MPEGVideoProvider : public VideoProvider {
private:
/// Pixel formats /// Pixel formats
enum Y4M_PixelFormat { enum Y4M_PixelFormat {
Y4M_PIXFMT_NONE = -1, /// not set/unknown Y4M_PIXFMT_NONE = -1, /// not set/unknown
@ -131,6 +125,8 @@ private:
int den; /// denominator int den; /// denominator
} fps_rat; /// framerate } fps_rat; /// framerate
agi::vfr::Framerate fps;
/// a list of byte positions detailing where in the file /// a list of byte positions detailing where in the file
/// each frame header can be found /// each frame header can be found
std::vector<int64_t> seek_table; std::vector<int64_t> seek_table;
@ -151,20 +147,13 @@ public:
~YUV4MPEGVideoProvider(); ~YUV4MPEGVideoProvider();
const AegiVideoFrame GetFrame(int n); const AegiVideoFrame GetFrame(int n);
int GetPosition();
int GetFrameCount();
int GetWidth(); int GetPosition() const { return cur_fn; }
int GetHeight(); int GetFrameCount() const { return num_frames; }
double GetFPS(); int GetWidth() const { return w; }
int GetHeight() const { return h; }
bool AreKeyFramesLoaded() { return false; } agi::vfr::Framerate GetFPS() const { return fps; }
wxArrayInt GetKeyFrames() { return wxArrayInt(); } std::vector<int> GetKeyFrames() const { return std::vector<int>(); };
bool IsVFR() { return false; }; wxString GetDecoderName() const { return L"YU4MPEG"; };
FrameRate GetTrueFrameRate() { return FrameRate(); } bool WantsCaching() const { return true; };
wxString GetDecoderName() { return L"YUV4MPEG"; }
bool WantsCaching() { return true; }
}; };

View File

@ -49,7 +49,6 @@
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
#include "video_slider.h" #include "video_slider.h"
@ -226,8 +225,8 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
if (canDrag) { if (canDrag) {
// Shift click to snap to keyframe // Shift click to snap to keyframe
if (shift && Display) { if (shift && Display) {
wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int keys = KeyFrames.Count(); int keys = KeyFrames.size();
int clickedFrame = GetValueAtX(x); int clickedFrame = GetValueAtX(x);
int closest = 0; int closest = 0;
int cur; int cur;
@ -332,8 +331,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
// Jump to next sub boundary // Jump to next sub boundary
if (direction != 0) { if (direction != 0) {
int target1 = VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true); int target1 = VideoContext::Get()->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START);
int target2 = VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),false); int target2 = VideoContext::Get()->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END);
bool drawn = false; bool drawn = false;
// Forward // Forward
@ -376,8 +375,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
// Prepare // Prepare
int prevKey = 0; int prevKey = 0;
int nextKey = VideoContext::Get()->GetLength()-1; int nextKey = VideoContext::Get()->GetLength()-1;
wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int keys = KeyFrames.Count(); int keys = KeyFrames.size();
int cur = VideoContext::Get()->GetFrameN(); int cur = VideoContext::Get()->GetFrameN();
int i; int i;
int temp; int temp;
@ -481,8 +480,8 @@ void VideoSlider::DrawImage(wxDC &destdc) {
int curX; int curX;
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) { if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
dc.SetPen(wxPen(shad)); dc.SetPen(wxPen(shad));
wxArrayInt KeyFrames = VideoContext::Get()->GetKeyFrames(); std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int keys = KeyFrames.Count(); int keys = KeyFrames.size();
for (int i=0;i<keys;i++) { for (int i=0;i<keys;i++) {
curX = GetXAtValue(KeyFrames[i]); curX = GetXAtValue(KeyFrames[i]);
dc.DrawLine(curX,2,curX,8); dc.DrawLine(curX,2,curX,8);

View File

@ -57,7 +57,6 @@
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
#include "video_provider_manager.h" #include "video_provider_manager.h"

View File

@ -41,7 +41,6 @@
#include "subs_edit_box.h" #include "subs_edit_box.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "vfr.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h" #include "video_display.h"
#include "visual_tool_drag.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 // Set time of clicked feature to the current frame and shift all other
// selected features by the same amount // selected features by the same amount
if (feature->type != DRAG_ORIGIN) { 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; int change = time - feature->time;
for (sel_iterator cur = selectedFeatures.begin(); cur != selectedFeatures.end(); ++cur) { for (sel_iterator cur = selectedFeatures.begin(); cur != selectedFeatures.end(); ++cur) {