forked from mia/Aegisub
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:
parent
9322f95071
commit
acba2c6b63
62 changed files with 680 additions and 2616 deletions
|
@ -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"
|
||||||
|
|
|
@ -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 ") {
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 () {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class wxWindow;
|
class wxWindow;
|
||||||
|
namespace agi { namespace vfr { class Framerate; } }
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
///
|
///
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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,9 +339,7 @@ bool DialogTimingProcessor::StyleOK(wxString styleName) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Sort dialogues
|
||||||
|
|
||||||
/// @brief Sort dialogues
|
|
||||||
///
|
///
|
||||||
void DialogTimingProcessor::SortDialogues() {
|
void DialogTimingProcessor::SortDialogues() {
|
||||||
// Copy from original to temporary list
|
// Copy from original to temporary list
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,118 +1069,100 @@ 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();
|
||||||
// Get frames
|
if (!con->IsLoaded() || !con->KeyFramesLoaded()) return;
|
||||||
wxArrayInt sel = SubsGrid->GetSelection();
|
|
||||||
int curFrame = VideoContext::Get()->GetFrameN();
|
|
||||||
int prev = 0;
|
|
||||||
int next = 0;
|
|
||||||
int frame = 0;
|
|
||||||
wxArrayInt keyframes = VideoContext::Get()->GetKeyFrames();
|
|
||||||
size_t n = keyframes.Count();
|
|
||||||
bool found = false;
|
|
||||||
for (size_t i=0;i<n;i++) {
|
|
||||||
frame = keyframes[i];
|
|
||||||
|
|
||||||
if (frame == curFrame) {
|
// Get frames
|
||||||
prev = frame;
|
wxArrayInt sel = SubsGrid->GetSelection();
|
||||||
if (i < n-1) next = keyframes[i+1];
|
int curFrame = con->GetFrameN();
|
||||||
else next = VideoContext::Get()->GetLength();
|
int prev = 0;
|
||||||
found = true;
|
int next = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame > curFrame) {
|
const std::vector<int> &keyframes = con->GetKeyFrames();
|
||||||
if (i != 0) prev = keyframes[i-1];
|
if (curFrame < keyframes.front()) {
|
||||||
else prev = 0;
|
next = keyframes.front();
|
||||||
next = frame;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last section?
|
|
||||||
if (!found) {
|
|
||||||
if (n > 0) prev = keyframes[n-1];
|
|
||||||
else prev = 0;
|
|
||||||
next = VideoContext::Get()->GetLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get times
|
|
||||||
int start_ms = VFR_Output.GetTimeAtFrame(prev,true);
|
|
||||||
int end_ms = VFR_Output.GetTimeAtFrame(next-1,false);
|
|
||||||
AssDialogue *cur;
|
|
||||||
|
|
||||||
// Update rows
|
|
||||||
for (size_t i=0;i<sel.Count();i++) {
|
|
||||||
cur = SubsGrid->GetDialogue(sel[i]);
|
|
||||||
cur->Start.SetMS(start_ms);
|
|
||||||
cur->End.SetMS(end_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit
|
|
||||||
SubsGrid->editBox->Update(true);
|
|
||||||
SubsGrid->ass->FlagAsModified(_("snap to scene"));
|
|
||||||
SubsGrid->CommitChanges();
|
|
||||||
}
|
}
|
||||||
|
else if (curFrame >= keyframes.back()) {
|
||||||
|
prev = keyframes.back();
|
||||||
|
next = con->GetLength();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::vector<int>::const_iterator kf = std::lower_bound(keyframes.begin(), keyframes.end(), curFrame);
|
||||||
|
if (*kf == curFrame) {
|
||||||
|
prev = *kf;
|
||||||
|
next = *(kf + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev = *(kf - 1);
|
||||||
|
next = *kf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get times
|
||||||
|
int start_ms = con->TimeAtFrame(prev,agi::vfr::START);
|
||||||
|
int end_ms = con->TimeAtFrame(next-1,agi::vfr::END);
|
||||||
|
AssDialogue *cur;
|
||||||
|
|
||||||
|
// Update rows
|
||||||
|
for (size_t i=0;i<sel.Count();i++) {
|
||||||
|
cur = SubsGrid->GetDialogue(sel[i]);
|
||||||
|
cur->Start.SetMS(start_ms);
|
||||||
|
cur->End.SetMS(end_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
SubsGrid->editBox->Update(true);
|
||||||
|
SubsGrid->ass->FlagAsModified(_("snap to scene"));
|
||||||
|
SubsGrid->CommitChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Shift to frame
|
/// @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();
|
|
||||||
size_t n=sels.Count();
|
|
||||||
if (n == 0) return;
|
|
||||||
|
|
||||||
// Get shifting in ms
|
wxArrayInt sels = SubsGrid->GetSelection();
|
||||||
AssDialogue *cur = SubsGrid->GetDialogue(sels[0]);
|
size_t n=sels.Count();
|
||||||
if (!cur) return;
|
if (n == 0) return;
|
||||||
int shiftBy = VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN(),true) - cur->Start.GetMS();
|
|
||||||
|
|
||||||
// Update
|
// Get shifting in ms
|
||||||
for (size_t i=0;i<n;i++) {
|
AssDialogue *cur = SubsGrid->GetDialogue(sels[0]);
|
||||||
cur = SubsGrid->GetDialogue(sels[i]);
|
if (!cur) return;
|
||||||
if (cur) {
|
int shiftBy = VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN(),agi::vfr::START) - cur->Start.GetMS();
|
||||||
cur->Start.SetMS(cur->Start.GetMS()+shiftBy);
|
|
||||||
cur->End.SetMS(cur->End.GetMS()+shiftBy);
|
// Update
|
||||||
}
|
for (size_t i=0;i<n;i++) {
|
||||||
|
cur = SubsGrid->GetDialogue(sels[i]);
|
||||||
|
if (cur) {
|
||||||
|
cur->Start.SetMS(cur->Start.GetMS()+shiftBy);
|
||||||
|
cur->End.SetMS(cur->End.GetMS()+shiftBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit
|
|
||||||
SubsGrid->ass->FlagAsModified(_("shift to frame"));
|
|
||||||
SubsGrid->CommitChanges();
|
|
||||||
SubsGrid->editBox->Update(true,false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
SubsGrid->ass->FlagAsModified(_("shift to frame"));
|
||||||
|
SubsGrid->CommitChanges();
|
||||||
|
SubsGrid->editBox->Update(true,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Undo
|
/// @brief Undo
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,26 +112,24 @@ 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;
|
||||||
|
|
||||||
// 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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::vector<int> times;
|
||||||
//std::sort<std::vector<double>::iterator>(timecodes.begin(),timecodes.end());
|
times.reserve(timecodes.size());
|
||||||
|
std::transform(timecodes.begin(), timecodes.end(), std::back_inserter(times), &mkv_round);
|
||||||
// Check if it's CFR
|
target = agi::vfr::Framerate(times);
|
||||||
/*
|
|
||||||
bool isCFR = true;
|
|
||||||
double estimateCFR = timecodes.back() / (timecodes.size()-1);
|
|
||||||
double t1,t2;
|
|
||||||
for (int i=1;i<frames;i++) {
|
|
||||||
t1 = timecodes[i];
|
|
||||||
t2 = timecodes[i-1];
|
|
||||||
int delta = abs(int(t1 - t2 - estimateCFR));
|
|
||||||
if (delta > 2) {
|
|
||||||
isCFR = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
bool isCFR = false;
|
|
||||||
double estimateCFR = 0;
|
|
||||||
|
|
||||||
// Constant framerate
|
|
||||||
if (isCFR) {
|
|
||||||
estimateCFR = 1/estimateCFR * 1000.0;
|
|
||||||
if (fabs(estimateCFR - 24000.0/1001.0) < 0.02) estimateCFR = 24000.0 / 1001.0;
|
|
||||||
if (fabs(estimateCFR - 30000.0/1001.0) < 0.02) estimateCFR = 30000.0 / 1001.0;
|
|
||||||
target.SetCFR(estimateCFR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable framerate
|
|
||||||
else {
|
|
||||||
std::vector<int> times;
|
|
||||||
for (int i=0;i<frames;i++) times.push_back(int(timecodes[i]+0.5));
|
|
||||||
target.SetVFR(times);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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 = 𝔠
|
||||||
FrameRate *rate = 𝔠
|
|
||||||
|
|
||||||
// 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 = 𝔠
|
||||||
FrameRate *rate = 𝔠
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
|
@ -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;
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,133 +141,82 @@ 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
|
try {
|
||||||
if (!filename.IsEmpty()) {
|
grid->CommitChanges(true);
|
||||||
|
|
||||||
|
// Set GL context
|
||||||
|
GetGLContext(displayList.front())->SetCurrent(*displayList.front());
|
||||||
|
|
||||||
|
// Choose a provider
|
||||||
|
provider.reset(VideoProviderFactoryManager::GetProvider(filename));
|
||||||
|
|
||||||
|
// Get subtitles provider
|
||||||
try {
|
try {
|
||||||
grid->CommitChanges(true);
|
subsProvider.reset(SubtitlesProviderFactoryManager::GetProvider());
|
||||||
|
|
||||||
// Set GL context
|
|
||||||
GetGLContext(displayList.front())->SetCurrent(*displayList.front());
|
|
||||||
|
|
||||||
// Choose a provider
|
|
||||||
provider = VideoProviderFactoryManager::GetProvider(filename);
|
|
||||||
loaded = provider != NULL;
|
|
||||||
|
|
||||||
// Get subtitles provider
|
|
||||||
try {
|
|
||||||
subsProvider = SubtitlesProviderFactoryManager::GetProvider();
|
|
||||||
}
|
|
||||||
catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider")); }
|
|
||||||
catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider")); }
|
|
||||||
|
|
||||||
KeyFrames.Clear();
|
|
||||||
// load keyframes if available
|
|
||||||
if (provider->AreKeyFramesLoaded()) {
|
|
||||||
KeyFrames = provider->GetKeyFrames();
|
|
||||||
keyFramesLoaded = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
keyFramesLoaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set frame rate
|
|
||||||
fps = provider->GetFPS();
|
|
||||||
// does this provider need special vfr treatment?
|
|
||||||
if (provider->NeedsVFRHack()) {
|
|
||||||
// FIXME:
|
|
||||||
// Unfortunately, this hack does not actually work for the one
|
|
||||||
// provider that needs it (Avisynth). Go figure.
|
|
||||||
bool isVfr = provider->IsVFR();
|
|
||||||
if (!isVfr || provider->IsNativelyByFrames()) {
|
|
||||||
VFR_Input.SetCFR(fps);
|
|
||||||
if (VFR_Output.GetFrameRateType() != VFR) VFR_Output.SetCFR(fps);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FrameRate temp = provider->GetTrueFrameRate();
|
|
||||||
provider->OverrideFrameTimeList(temp.GetFrameTimeList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gather video parameters
|
|
||||||
length = provider->GetFrameCount();
|
|
||||||
w = provider->GetWidth();
|
|
||||||
h = provider->GetHeight();
|
|
||||||
|
|
||||||
// Set filename
|
|
||||||
videoName = filename;
|
|
||||||
config::mru->Add("Video", STD_STR(filename));
|
|
||||||
wxFileName fn(filename);
|
|
||||||
StandardPaths::SetPathValue(_T("?video"),fn.GetPath());
|
|
||||||
|
|
||||||
// Get frame
|
|
||||||
frame_n = 0;
|
|
||||||
|
|
||||||
// Show warning
|
|
||||||
wxString warning = provider->GetWarning().c_str();
|
|
||||||
if (!warning.IsEmpty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK);
|
|
||||||
|
|
||||||
hasSubtitles = false;
|
|
||||||
if (filename.Right(4).Lower() == L".mkv") {
|
|
||||||
hasSubtitles = MatroskaWrapper::HasSubtitles(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateDisplays(true);
|
|
||||||
}
|
}
|
||||||
|
catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider")); }
|
||||||
catch (wxString &e) {
|
catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider")); }
|
||||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
|
||||||
|
keyFrames = provider->GetKeyFrames();
|
||||||
|
|
||||||
|
// Set frame rate
|
||||||
|
videoFPS = provider->GetFPS();
|
||||||
|
if (ovrFPS.IsLoaded()) {
|
||||||
|
int ovr = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION);
|
||||||
|
if (ovr == wxYES) {
|
||||||
|
ovrFPS = agi::vfr::Framerate();
|
||||||
|
ovrTimecodeFile.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gather video parameters
|
||||||
|
length = provider->GetFrameCount();
|
||||||
|
|
||||||
|
// Set filename
|
||||||
|
videoName = filename;
|
||||||
|
config::mru->Add("Video", STD_STR(filename));
|
||||||
|
wxFileName fn(filename);
|
||||||
|
StandardPaths::SetPathValue(_T("?video"),fn.GetPath());
|
||||||
|
|
||||||
|
// Get frame
|
||||||
|
frame_n = 0;
|
||||||
|
|
||||||
|
// Show warning
|
||||||
|
wxString warning = provider->GetWarning();
|
||||||
|
if (!warning.empty()) wxMessageBox(warning,_T("Warning"),wxICON_WARNING | wxOK);
|
||||||
|
|
||||||
|
hasSubtitles = false;
|
||||||
|
if (filename.Right(4).Lower() == L".mkv") {
|
||||||
|
hasSubtitles = MatroskaWrapper::HasSubtitles(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDisplays(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (wxString &e) {
|
||||||
|
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Add new display
|
|
||||||
/// @param display
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void VideoContext::AddDisplay(VideoDisplay *display) {
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,10 +142,10 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
||||||
decoderName = _T("Mpeg2Dec3_Mpeg2Source");
|
decoderName = _T("Mpeg2Dec3_Mpeg2Source");
|
||||||
|
|
||||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||||
if (env->FunctionExists("SetPlanarLegacyAlignment")) {
|
if (env->FunctionExists("SetPlanarLegacyAlignment")) {
|
||||||
AVSValue args[2] = { script, true };
|
AVSValue args[2] = { script, true };
|
||||||
script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2));
|
script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +155,8 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
script = env->Invoke("Mpeg2Source", videoFilename);
|
||||||
decoderName = _T("DGDecode_Mpeg2Source");
|
decoderName = _T("DGDecode_Mpeg2Source");
|
||||||
|
|
||||||
//note that DGDecode will also have issues like if the version is too ancient but no sane person
|
//note that DGDecode will also have issues like if the version is too ancient but no sane person
|
||||||
//would use that anyway
|
//would use that anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) {
|
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) {
|
||||||
|
@ -177,9 +164,9 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
script = env->Invoke("Mpeg2Source", videoFilename);
|
||||||
decoderName = _T("Mpeg2Source");
|
decoderName = _T("Mpeg2Source");
|
||||||
|
|
||||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||||
if (env->FunctionExists("SetPlanarLegacyAlignment"))
|
if (env->FunctionExists("SetPlanarLegacyAlignment"))
|
||||||
script = env->Invoke("SetPlanarLegacyAlignment", script);
|
script = env->Invoke("SetPlanarLegacyAlignment", script);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some other format, such as mkv, mp4, ogm... try both flavors of DirectShowSource
|
// Some other format, such as mkv, mp4, ogm... try both flavors of DirectShowSource
|
||||||
|
@ -253,30 +240,16 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read keyframes and timecodes from MKV file
|
// 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;
|
|
||||||
|
MatroskaWrapper::wrapper.SetToTimecodes(vfr_fps);
|
||||||
// Ask to override timecodes
|
|
||||||
int override = wxYES;
|
|
||||||
if (VFR_Output.IsLoaded()) override = wxMessageBox(_("You already have timecodes loaded. Replace them with the timecodes from the Matroska file?"),_("Replace timecodes?"),wxYES_NO | wxICON_QUESTION);
|
|
||||||
if (override == wxYES) {
|
|
||||||
MatroskaWrapper::wrapper.SetToTimecodes(temp);
|
|
||||||
isVfr = temp.GetFrameRateType() == VFR;
|
|
||||||
if (isVfr) {
|
|
||||||
MatroskaWrapper::wrapper.SetToTimecodes(VFR_Input);
|
|
||||||
MatroskaWrapper::wrapper.SetToTimecodes(VFR_Output);
|
|
||||||
trueFrameRate = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -197,7 +194,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer));
|
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +246,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
const FFMS_FrameInfo *CurFrameData;
|
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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue