The big VideoDisplay split
Originally committed to SVN as r20.
This commit is contained in:
parent
cb573429fb
commit
227febdd24
8 changed files with 480 additions and 672 deletions
|
@ -191,7 +191,7 @@ int DialogProperties::SetInfoIfDifferent(wxString key,wxString value) {
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Set res to match video
|
// Set res to match video
|
||||||
void DialogProperties::OnSetFromVideo(wxCommandEvent &event) {
|
void DialogProperties::OnSetFromVideo(wxCommandEvent &event) {
|
||||||
ResX->SetValue(wxString::Format(_T("%i"),vid->orig_w));
|
ResX->SetValue(wxString::Format(_T("%i"),vid->provider->GetSourceWidth())); //fix me, null check?
|
||||||
ResY->SetValue(wxString::Format(_T("%i"),vid->orig_h));
|
ResY->SetValue(wxString::Format(_T("%i"),vid->provider->GetSourceHeight())); //fix me, identical to other set?
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,8 +232,8 @@ void DialogResample::OnResample (wxCommandEvent &event) {
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// Get destination resolution from video
|
// Get destination resolution from video
|
||||||
void DialogResample::OnGetDestRes (wxCommandEvent &event) {
|
void DialogResample::OnGetDestRes (wxCommandEvent &event) {
|
||||||
ResX->SetValue(wxString::Format(_T("%i"),vid->orig_w));
|
ResX->SetValue(wxString::Format(_T("%i"),vid->provider->GetSourceWidth())); //fix me, null check?
|
||||||
ResY->SetValue(wxString::Format(_T("%i"),vid->orig_h));
|
ResY->SetValue(wxString::Format(_T("%i"),vid->provider->GetSourceHeight()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -465,8 +465,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
bool isFile = true;
|
bool isFile = (filename != _T(""));
|
||||||
if (filename == _T("")) isFile = false;
|
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
try {
|
try {
|
||||||
|
@ -513,7 +512,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
SynchronizeProject(true);
|
SynchronizeProject(true);
|
||||||
|
|
||||||
// Update video
|
// Update video
|
||||||
videoBox->videoDisplay->SetSubtitles(filename);
|
//videoBox->videoDisplay->SetSubtitles(filename); //fix me, remove?
|
||||||
|
|
||||||
// Update title bar
|
// Update title bar
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
|
@ -523,9 +522,6 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
//////////////////
|
//////////////////
|
||||||
// Save subtitles
|
// Save subtitles
|
||||||
bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
|
bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
|
||||||
// Synchronize
|
|
||||||
SynchronizeProject();
|
|
||||||
|
|
||||||
// Try to get filename from file
|
// Try to get filename from file
|
||||||
wxString filename;
|
wxString filename;
|
||||||
if (saveas == false && AssFile::top->IsASS) filename = AssFile::top->filename;
|
if (saveas == false && AssFile::top->IsASS) filename = AssFile::top->filename;
|
||||||
|
@ -534,8 +530,12 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
|
||||||
if (filename == _T("")) {
|
if (filename == _T("")) {
|
||||||
videoBox->videoDisplay->Stop();
|
videoBox->videoDisplay->Stop();
|
||||||
filename = wxFileSelector(_("Save subtitles file"),_T(""),_T(""),_T(""),_T("Advanced Substation Alpha (*.ass)|*.ass"),wxSAVE | wxOVERWRITE_PROMPT,this);
|
filename = wxFileSelector(_("Save subtitles file"),_T(""),_T(""),_T(""),_T("Advanced Substation Alpha (*.ass)|*.ass"),wxSAVE | wxOVERWRITE_PROMPT,this);
|
||||||
|
AssFile::top->filename = filename; //fix me, ghetto hack for correct relative path generation in SynchronizeProject()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Synchronize
|
||||||
|
SynchronizeProject();
|
||||||
|
|
||||||
// Actually save
|
// Actually save
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
// Get charset
|
// Get charset
|
||||||
|
@ -548,7 +548,7 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
try {
|
try {
|
||||||
videoBox->videoDisplay->SetSubtitles(filename);
|
//videoBox->videoDisplay->SetSubtitles(filename); fix me, remove?
|
||||||
AssFile::top->Save(filename,true,true,charset);
|
AssFile::top->Save(filename,true,true,charset);
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
}
|
}
|
||||||
|
@ -641,7 +641,6 @@ void FrameMain::SetDisplayMode(int mode) {
|
||||||
// Update
|
// Update
|
||||||
curMode = mode;
|
curMode = mode;
|
||||||
UpdateToolbar();
|
UpdateToolbar();
|
||||||
videoBox->videoDisplay->RefreshVideo();
|
|
||||||
videoBox->VideoSizer->Layout();
|
videoBox->VideoSizer->Layout();
|
||||||
MainSizer->Layout();
|
MainSizer->Layout();
|
||||||
//Layout();
|
//Layout();
|
||||||
|
@ -760,8 +759,6 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
|
||||||
|
|
||||||
// Video
|
// Video
|
||||||
if (curSubsVideo != videoBox->videoDisplay->videoName) {
|
if (curSubsVideo != videoBox->videoDisplay->videoName) {
|
||||||
videoBox->videoDisplay->Locked(true);
|
|
||||||
videoBox->videoDisplay->Reset();
|
|
||||||
if (curSubsVideo != _T("")) {
|
if (curSubsVideo != _T("")) {
|
||||||
LoadVideo(curSubsVideo);
|
LoadVideo(curSubsVideo);
|
||||||
if (videoBox->videoDisplay->loaded) {
|
if (videoBox->videoDisplay->loaded) {
|
||||||
|
@ -770,7 +767,6 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
|
||||||
videoBox->videoDisplay->SetZoomPos(videoZoom-1);
|
videoBox->videoDisplay->SetZoomPos(videoZoom-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
videoBox->videoDisplay->Locked(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
|
@ -851,7 +847,7 @@ void FrameMain::LoadVideo(wxString file,bool autoload) {
|
||||||
if (videoBox->videoDisplay->loaded) {
|
if (videoBox->videoDisplay->loaded) {
|
||||||
int scriptx = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResX"));
|
int scriptx = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResX"));
|
||||||
int scripty = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResY"));
|
int scripty = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResY"));
|
||||||
int vidx = videoBox->videoDisplay->orig_w, vidy = videoBox->videoDisplay->orig_h;
|
int vidx = videoBox->videoDisplay->provider->GetSourceWidth(), vidy = videoBox->videoDisplay->provider->GetSourceHeight();
|
||||||
if (scriptx != vidx || scripty != vidy) {
|
if (scriptx != vidx || scripty != vidy) {
|
||||||
switch (Options.AsInt(_T("Video Check Script Res"))) {
|
switch (Options.AsInt(_T("Video Check Script Res"))) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -929,7 +925,6 @@ void FrameMain::LoadVFR(wxString filename) {
|
||||||
|
|
||||||
SubsBox->CommitChanges();
|
SubsBox->CommitChanges();
|
||||||
EditBox->UpdateFrameTiming();
|
EditBox->UpdateFrameTiming();
|
||||||
//SynchronizeProject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1640,7 +1640,9 @@ void SubtitlesGrid::CommitChanges(bool force) {
|
||||||
// Export
|
// Export
|
||||||
wxString workfile = GetTempWorkFile();
|
wxString workfile = GetTempWorkFile();
|
||||||
ass->Export(workfile);
|
ass->Export(workfile);
|
||||||
video->RefreshVideo(true);
|
|
||||||
|
if (video->loaded)
|
||||||
|
video->RefreshSubtitles();
|
||||||
|
|
||||||
// Resume play
|
// Resume play
|
||||||
if (playing) video->Play();
|
if (playing) video->Play();
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
////////////
|
////////////
|
||||||
// Includes
|
// Includes
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "avisynth_wrap.h"
|
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
|
@ -86,22 +85,18 @@ END_EVENT_TABLE()
|
||||||
VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
VideoDisplay::VideoDisplay(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)
|
||||||
{
|
{
|
||||||
|
provider = NULL;
|
||||||
curLine = NULL;
|
curLine = NULL;
|
||||||
curFrame = NULL;
|
|
||||||
backbuffer = NULL;
|
backbuffer = NULL;
|
||||||
ControlSlider = NULL;
|
ControlSlider = NULL;
|
||||||
PositionDisplay = NULL;
|
PositionDisplay = NULL;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
frame_n = 0;
|
frame_n = 0;
|
||||||
origSize = size;
|
origSize = size;
|
||||||
zoom = 0.75;
|
|
||||||
arType = 0;
|
arType = 0;
|
||||||
isLocked = false;
|
|
||||||
gettingFrame = false;
|
|
||||||
IsPlaying = false;
|
IsPlaying = false;
|
||||||
threaded = Options.AsBool(_T("Threaded Video"));
|
threaded = Options.AsBool(_T("Threaded Video"));
|
||||||
nextFrame = -1;
|
nextFrame = -1;
|
||||||
framesSkipped = 0;
|
|
||||||
|
|
||||||
// Create PNG handler
|
// Create PNG handler
|
||||||
wxPNGHandler *png = new wxPNGHandler;
|
wxPNGHandler *png = new wxPNGHandler;
|
||||||
|
@ -116,445 +111,94 @@ VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos,
|
||||||
//////////////
|
//////////////
|
||||||
// Destructor
|
// Destructor
|
||||||
VideoDisplay::~VideoDisplay () {
|
VideoDisplay::~VideoDisplay () {
|
||||||
ControlSlider = NULL;
|
SetVideo(_T(""));
|
||||||
Unload();
|
delete backbuffer;
|
||||||
if (backbuffer) delete backbuffer;
|
|
||||||
backbuffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////
|
void VideoDisplay::UpdateSize() {
|
||||||
// Sets video filename
|
if (provider) {
|
||||||
void VideoDisplay::SetVideo(const wxString &filename) {
|
w = provider->GetWidth();
|
||||||
try {
|
h = provider->GetHeight();
|
||||||
if (!filename.empty()) {
|
|
||||||
// Verify if file exists
|
|
||||||
wxFileName filetest(filename);
|
|
||||||
if (!filetest.FileExists()) throw _T("File not found.");
|
|
||||||
|
|
||||||
// OK to load
|
|
||||||
if (videoName != filename) {
|
|
||||||
Unload();
|
|
||||||
videoName = filename;
|
|
||||||
OpenAVSVideo();
|
|
||||||
if (!loaded) Reset();
|
|
||||||
else RefreshVideo();
|
|
||||||
|
|
||||||
// Set keyframes
|
|
||||||
if (filename.Right(4).Lower() == _T(".avi")) KeyFrames = VFWWrapper::GetKeyFrames(filename);
|
|
||||||
else KeyFrames.Clear();
|
|
||||||
|
|
||||||
// Add to recent
|
|
||||||
Options.AddToRecentList(filename,_T("Recent vid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
else Reset();
|
|
||||||
}
|
|
||||||
else Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (wchar_t *error) {
|
|
||||||
wxMessageBox(error,_T("Error setting video"),wxICON_ERROR | wxOK);
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (...) {
|
|
||||||
wxMessageBox(_T("Unhandled exception"),_T("Error setting video"),wxICON_ERROR | wxOK);
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Sets subtitles filename
|
|
||||||
void VideoDisplay::SetSubtitles(const wxString &filename) {
|
|
||||||
if (!loaded) return;
|
|
||||||
wxString old = subsName;
|
|
||||||
subsName = filename;
|
|
||||||
|
|
||||||
if (!videoName.empty()) {
|
|
||||||
OpenAVSSubs();
|
|
||||||
RefreshVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////
|
|
||||||
// Open AVS
|
|
||||||
void VideoDisplay::OpenAVSVideo() {
|
|
||||||
if (videoName.empty()) return;
|
|
||||||
bool directShow = false;
|
|
||||||
|
|
||||||
// Create AviSynth environment
|
|
||||||
{
|
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
|
||||||
AVSValue script;
|
|
||||||
|
|
||||||
// Load VSFilter
|
|
||||||
try {
|
|
||||||
env->Invoke("LoadPlugin", env->SaveString(GetVSFilter().mb_str(wxConvLocal)));
|
|
||||||
}
|
|
||||||
catch (AvisynthError &) {
|
|
||||||
throw _T("Failed opening VSfilter");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Prepare filename
|
|
||||||
char *videoFilename = env->SaveString(videoName.mb_str(wxConvLocal));
|
|
||||||
|
|
||||||
wxString extension = videoName.Right(4);
|
|
||||||
extension.LowerCase();
|
|
||||||
|
|
||||||
// Load depending on extension
|
|
||||||
if (extension == _T(".avs")) {
|
|
||||||
script = env->Invoke("Import", videoFilename);
|
|
||||||
} else if (extension == _T(".avi")) {
|
|
||||||
try {
|
|
||||||
const char *argnames[2] = { 0, "audio" };
|
|
||||||
AVSValue args[2] = { videoFilename, false };
|
|
||||||
script = env->Invoke("AviSource", AVSValue(args,2), argnames);
|
|
||||||
//fix me, check for video?
|
|
||||||
} catch (AvisynthError &) {
|
|
||||||
const char *argnames[3] = { 0, "video", "audio" };
|
|
||||||
AVSValue args[3] = { videoFilename, true, false };
|
|
||||||
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
|
|
||||||
directShow = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (extension == _T(".d2v") && env->FunctionExists("mpeg2dec3_Mpeg2Source")) //prefer mpeg2dec3
|
|
||||||
script = env->Invoke("mpeg2dec3_Mpeg2Source", videoFilename);
|
|
||||||
else if (extension == _T(".d2v")) //try other mpeg2source
|
|
||||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
|
||||||
else {
|
|
||||||
const char *argnames[3] = { 0, "video", "audio" };
|
|
||||||
AVSValue args[3] = { videoFilename, true, false };
|
|
||||||
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
|
|
||||||
directShow = true;
|
|
||||||
}
|
|
||||||
} catch (AvisynthError &err) {
|
|
||||||
wxMessageBox (wxString(_T("AviSynth error: ")) + wxString(err.msg,wxConvLocal), _T("Error"), wxOK | wxICON_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if video is valid
|
|
||||||
PClip clip = script.AsClip();
|
|
||||||
VideoInfo vi = clip->GetVideoInfo();
|
|
||||||
|
|
||||||
if (!vi.HasVideo())
|
|
||||||
wxMessageBox (wxString(_T("No video found: ")), _T("Error"), wxOK | wxICON_ERROR);
|
|
||||||
|
|
||||||
// Get resolution
|
|
||||||
orig_w = vi.width;
|
|
||||||
orig_h = vi.height;
|
|
||||||
|
|
||||||
// Convert to RGB32 if needed
|
|
||||||
script = env->Invoke("ConvertToRGB32", clip);
|
|
||||||
|
|
||||||
// Cache
|
|
||||||
sublessVideo = (env->Invoke("InternalCache", script)).AsClip();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue with subs
|
|
||||||
OpenAVSSubs();
|
|
||||||
|
|
||||||
// Issue warning if it's DirectShow
|
|
||||||
if (directShow) wxMessageBox (_("This file is being loaded using DirectShow, which has UNRELIABLE seeking. Frame numbers MIGHT NOT match display, so precise timing CANNOT be trusted."), _("Warning!"), wxOK | wxICON_WARNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////
|
|
||||||
// Opens subtitles
|
|
||||||
void VideoDisplay::OpenAVSSubs () {
|
|
||||||
// Vars
|
|
||||||
{
|
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
|
||||||
AVSValue script;
|
|
||||||
video = sublessVideo;
|
|
||||||
|
|
||||||
// Make sure there is a workfile
|
|
||||||
wxString workfile = grid->GetTempWorkFile();
|
|
||||||
wxFileName file(workfile);
|
|
||||||
if (!file.FileExists()) {
|
|
||||||
grid->CommitChanges(true);
|
|
||||||
}
|
|
||||||
if (!file.FileExists()) {
|
|
||||||
throw _T("Failed creating temporary subs file. Make sure you have write permission on folder.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert subs
|
|
||||||
try {
|
|
||||||
PClip clip = video;
|
|
||||||
char temp[512];
|
|
||||||
strcpy(temp,workfile.mb_str(wxConvLocal));
|
|
||||||
AVSValue args1[2] = { clip, temp };
|
|
||||||
script = env->Invoke("TextSub", AVSValue(args1,2));
|
|
||||||
video = script.AsClip();
|
|
||||||
} catch (AvisynthError &err) {
|
|
||||||
wxMessageBox (wxString(_T("AviSynth error: ")) + wxString(err.msg,wxConvLocal), _T("Error"), wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zoom & AR
|
|
||||||
if (zoom != 1.0 || arType != 0) {
|
|
||||||
try {
|
|
||||||
// Get video data
|
|
||||||
PClip clip = video;
|
|
||||||
VideoInfo vi = clip->GetVideoInfo();
|
|
||||||
|
|
||||||
// Get aspect ratio data
|
|
||||||
int pos_h = vi.height;
|
|
||||||
int pos_w = vi.width;
|
|
||||||
switch (arType) {
|
|
||||||
case 1: pos_w = pos_h * 4 / 3; break;
|
|
||||||
case 2: pos_w = pos_h * 16 / 9; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize
|
|
||||||
AVSValue args[3] = { clip, int(zoom*pos_w), int(zoom*pos_h) };
|
|
||||||
script = env->Invoke(Options.AsText(_T("Video resizer")).mb_str(wxConvLocal), AVSValue(args,3));
|
|
||||||
video = script.AsClip();
|
|
||||||
} catch (AvisynthError &err) {
|
|
||||||
wxMessageBox (wxString(_T("AviSynth error: ")) + wxString(err.msg,wxConvLocal), _T("Error"), wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache
|
|
||||||
video = (env->Invoke("InternalCache", video)).AsClip();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set final
|
|
||||||
PrepareAfterAVS();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////
|
|
||||||
// Sets control up after loading an AVS
|
|
||||||
void VideoDisplay::PrepareAfterAVS() {
|
|
||||||
{
|
|
||||||
// Gather video parameters
|
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
|
||||||
VideoInfo vi = video->GetVideoInfo();
|
|
||||||
w = vi.width;
|
|
||||||
h = vi.height;
|
|
||||||
length = vi.num_frames;
|
|
||||||
if (vi.fps_denominator != 0) fps = double(vi.fps_numerator) / double(vi.fps_denominator);
|
|
||||||
else fps = 0;
|
|
||||||
VFR_Input.SetCFR(fps);
|
|
||||||
if (!VFR_Output.loaded) VFR_Output.SetCFR(fps,true);
|
|
||||||
|
|
||||||
// Set the size for this control
|
// Set the size for this control
|
||||||
SetClientSize(w,h);
|
SetClientSize(w,h);
|
||||||
int _w,_h;
|
int _w,_h;
|
||||||
GetSize(&_w,&_h);
|
GetSize(&_w,&_h);
|
||||||
SetSizeHints(_w,_h,_w,_h);
|
SetSizeHints(_w,_h,_w,_h);
|
||||||
|
|
||||||
// Set range of slider
|
|
||||||
if (ControlSlider) ControlSlider->SetRange(0,vi.num_frames-1);
|
|
||||||
|
|
||||||
// Clear frame
|
|
||||||
if (curFrame) delete curFrame;
|
|
||||||
curFrame = NULL;
|
|
||||||
|
|
||||||
// Flag as loaded
|
|
||||||
loaded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
///////////
|
// Sets video filename
|
||||||
// Unloads
|
void VideoDisplay::SetVideo(const wxString &filename) {
|
||||||
void VideoDisplay::Unload() {
|
if (filename == _T("")) {
|
||||||
{
|
delete provider;
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
provider = NULL;
|
||||||
|
|
||||||
// AviSynth cleanup
|
|
||||||
video = NULL;
|
|
||||||
sublessVideo = NULL;
|
|
||||||
|
|
||||||
// Internal cleanup
|
|
||||||
loaded = false;
|
|
||||||
if (curFrame) delete curFrame;
|
|
||||||
curFrame = NULL;
|
|
||||||
videoName = _T("");
|
|
||||||
if (VFR_Output.vfr == NULL) VFR_Output.Unload();
|
if (VFR_Output.vfr == NULL) VFR_Output.Unload();
|
||||||
VFR_Input.Unload();
|
VFR_Input.Unload();
|
||||||
|
|
||||||
|
videoName = _T("");
|
||||||
|
|
||||||
frame_n = 0;
|
frame_n = 0;
|
||||||
if (ControlSlider) {
|
|
||||||
ControlSlider->SetRange(0,0);
|
Reset();
|
||||||
|
} else {
|
||||||
|
SetVideo(_T(""));
|
||||||
|
|
||||||
|
try {
|
||||||
|
grid->CommitChanges(true);
|
||||||
|
|
||||||
|
bool usedDirectshow;
|
||||||
|
|
||||||
|
provider = new VideoProvider(filename,grid->GetTempWorkFile(),0.75,usedDirectshow,true);
|
||||||
|
|
||||||
|
// Set keyframes
|
||||||
|
if (filename.Right(4).Lower() == _T(".avi"))
|
||||||
|
KeyFrames = VFWWrapper::GetKeyFrames(filename);
|
||||||
|
else
|
||||||
|
KeyFrames.Clear();
|
||||||
|
|
||||||
|
UpdateSize();
|
||||||
|
|
||||||
|
//Gather video parameters
|
||||||
|
length = provider->GetFrameCount();
|
||||||
|
fps = provider->GetFPS();
|
||||||
|
VFR_Input.SetCFR(fps);
|
||||||
|
if (!VFR_Output.loaded) VFR_Output.SetCFR(fps,true);
|
||||||
|
|
||||||
|
// Set range of slider
|
||||||
|
ControlSlider->SetRange(0,length-1);
|
||||||
ControlSlider->SetValue(0);
|
ControlSlider->SetValue(0);
|
||||||
|
|
||||||
|
videoName = filename;
|
||||||
|
|
||||||
|
// Add to recent
|
||||||
|
Options.AddToRecentList(filename,_T("Recent vid"));
|
||||||
|
|
||||||
|
RefreshVideo();
|
||||||
|
} catch (wxString &e) {
|
||||||
|
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
loaded = provider != NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
// Resets
|
// Resets
|
||||||
void VideoDisplay::Reset() {
|
void VideoDisplay::Reset() {
|
||||||
Unload();
|
|
||||||
w = origSize.GetX();
|
w = origSize.GetX();
|
||||||
h = origSize.GetY();
|
h = origSize.GetY();
|
||||||
SetClientSize(w,h);
|
SetClientSize(w,h);
|
||||||
int _w,_h;
|
int _w,_h;
|
||||||
GetSize(&_w,&_h);
|
GetSize(&_w,&_h);
|
||||||
SetSizeHints(_w,_h,_w,_h);
|
SetSizeHints(_w,_h,_w,_h);
|
||||||
RefreshVideo();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoDisplay::RefreshSubtitles() {
|
||||||
//////////////////////
|
provider->RefreshSubtitles();
|
||||||
// Gets a frame image
|
RefreshVideo();
|
||||||
void VideoDisplay::GetFrameImage(int n) {
|
|
||||||
// Prepare copy
|
|
||||||
unsigned char *data;
|
|
||||||
VideoInfo vi = video->GetVideoInfo();
|
|
||||||
PVideoFrame avsFrame;
|
|
||||||
try {
|
|
||||||
avsFrame = video->GetFrame(n,env);
|
|
||||||
}
|
|
||||||
catch (AvisynthError err) {
|
|
||||||
wxMessageBox (wxString(_T("AviSynth error: ")) + wxString(err.msg,wxConvLocal), _T("Error getting frame"), wxOK | wxICON_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
wxMessageBox(_T("AviSynth threw an exception while trying to retrieve frame."),_T("Error getting frame"),wxICON_ERROR | wxOK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned int pitch = avsFrame->GetPitch();
|
|
||||||
unsigned int read_w = avsFrame->GetRowSize();
|
|
||||||
unsigned int read_h = avsFrame->GetHeight();
|
|
||||||
int depth = wxDisplayDepth();
|
|
||||||
int bpp = depth/8;
|
|
||||||
unsigned int x,y,dx;
|
|
||||||
|
|
||||||
// Output
|
|
||||||
data = (unsigned char*) malloc(w*h*bpp);
|
|
||||||
|
|
||||||
// RGB24
|
|
||||||
if (vi.IsRGB24()) {
|
|
||||||
if (depth == 16) {
|
|
||||||
// Get pointers
|
|
||||||
const unsigned char *read_ptr = avsFrame->GetReadPtr();
|
|
||||||
unsigned short *write_ptr = (unsigned short*) (data+(w*h*2));
|
|
||||||
unsigned char r,g,b;
|
|
||||||
|
|
||||||
for (y=0;y<read_h;y++) {
|
|
||||||
write_ptr = write_ptr - read_w/3;
|
|
||||||
for (x=0,dx=0;x<read_w;x+=3,dx++) {
|
|
||||||
r = *(read_ptr+x+2);
|
|
||||||
g = *(read_ptr+x+1);
|
|
||||||
b = *(read_ptr+x);
|
|
||||||
*(write_ptr+dx) = ((r>>3)<<11) | ((g>>2)<<5) | b>>3;
|
|
||||||
}
|
|
||||||
read_ptr = read_ptr + pitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 24) {
|
|
||||||
// Get pointers
|
|
||||||
const unsigned char *read_ptr = avsFrame->GetReadPtr();
|
|
||||||
unsigned char *write_ptr = data+(w*h*3);
|
|
||||||
|
|
||||||
for (y=0;y<read_h;y++) {
|
|
||||||
write_ptr = write_ptr - read_w;
|
|
||||||
for (x=0;x<read_w;x+=3) {
|
|
||||||
*(write_ptr+x) = *(read_ptr+x);
|
|
||||||
*(write_ptr+x+1) = *(read_ptr+x+1);
|
|
||||||
*(write_ptr+x+2) = *(read_ptr+x+2);
|
|
||||||
}
|
|
||||||
read_ptr = read_ptr + pitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 32) {
|
|
||||||
// Get pointers
|
|
||||||
const unsigned char *read_ptr = avsFrame->GetReadPtr();
|
|
||||||
unsigned char *write_ptr = data+(w*h*4);
|
|
||||||
unsigned int delta = pitch-read_w;
|
|
||||||
unsigned int linelen = read_w*4/3;
|
|
||||||
int wid = read_w/3;
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
for (j=read_h;--j>=0;) {
|
|
||||||
write_ptr -= linelen;
|
|
||||||
for (i=wid;--i>=0;) {
|
|
||||||
*(write_ptr++) = *(read_ptr++);
|
|
||||||
*(write_ptr++) = *(read_ptr++);
|
|
||||||
*(write_ptr++) = *(read_ptr++);
|
|
||||||
write_ptr++;
|
|
||||||
}
|
|
||||||
read_ptr = read_ptr += delta;
|
|
||||||
write_ptr -= linelen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RGB32
|
|
||||||
else if (vi.IsRGB32()) {
|
|
||||||
if (depth == 8) {
|
|
||||||
throw _T("8-bit display not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 15) {
|
|
||||||
throw _T("15-bit display not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 16) {
|
|
||||||
// Get pointers
|
|
||||||
const unsigned char *read_ptr = avsFrame->GetReadPtr();
|
|
||||||
unsigned short *write_ptr = (unsigned short*) (data+(w*h*2));
|
|
||||||
unsigned char r,g,b;
|
|
||||||
|
|
||||||
for (y=0;y<read_h;y++) {
|
|
||||||
write_ptr = write_ptr - read_w/4;
|
|
||||||
for (x=0,dx=0;x<read_w;x+=4,dx++) {
|
|
||||||
r = *(read_ptr+x+2);
|
|
||||||
g = *(read_ptr+x+1);
|
|
||||||
b = *(read_ptr+x);
|
|
||||||
*(write_ptr+dx) = ((r>>3)<<11) | ((g>>2)<<5) | b>>3;
|
|
||||||
}
|
|
||||||
read_ptr = read_ptr + pitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 24) {
|
|
||||||
throw _T("24-bit display not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 32) {
|
|
||||||
// Get pointers
|
|
||||||
const unsigned int *read_ptr = (const unsigned int *) avsFrame->GetReadPtr();
|
|
||||||
unsigned int *write_ptr = ((unsigned int *) (data))+(w*h);
|
|
||||||
unsigned int delta = (pitch-read_w)/4;
|
|
||||||
unsigned int linelen = read_w/4;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=read_h;--i>=0;) {
|
|
||||||
write_ptr -= linelen;
|
|
||||||
memcpy(write_ptr,read_ptr,read_w);
|
|
||||||
read_ptr += linelen + delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
throw _T("Wrong colour format.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to image
|
|
||||||
BitmapMutex.Lock();
|
|
||||||
try {
|
|
||||||
if (curFrame) {
|
|
||||||
delete curFrame;
|
|
||||||
curFrame = NULL;
|
|
||||||
}
|
|
||||||
curFrame = new wxBitmap((const char*)data,w,h,depth);
|
|
||||||
}
|
|
||||||
catch (...) {}
|
|
||||||
BitmapMutex.Unlock();
|
|
||||||
free(data);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
frame_n = n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,27 +207,10 @@ void VideoDisplay::GetFrameImage(int n) {
|
||||||
void VideoDisplay::OnPaint(wxPaintEvent& event) {
|
void VideoDisplay::OnPaint(wxPaintEvent& event) {
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
|
|
||||||
// Try to grab frame if none
|
|
||||||
{
|
|
||||||
wxMutexLocker locker(BitmapMutex);
|
|
||||||
if (!curFrame) GetFrame(frame_n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw frame
|
// Draw frame
|
||||||
if (curFrame) {
|
dc.BeginDrawing();
|
||||||
wxMutexLocker locker(BitmapMutex);
|
dc.DrawBitmap(GetFrame(frame_n),0,0);
|
||||||
dc.BeginDrawing();
|
dc.EndDrawing();
|
||||||
dc.DrawBitmap(*curFrame,0,0);
|
|
||||||
dc.EndDrawing();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failed
|
|
||||||
else {
|
|
||||||
dc.BeginDrawing();
|
|
||||||
dc.SetBrush(*wxBLUE_BRUSH);
|
|
||||||
dc.DrawRectangle(0,0,w,h);
|
|
||||||
dc.EndDrawing();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -640,7 +267,6 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) {
|
||||||
if (needCreate) backbuffer = new wxBitmap(w,h);
|
if (needCreate) backbuffer = new wxBitmap(w,h);
|
||||||
|
|
||||||
// Prepare drawing
|
// Prepare drawing
|
||||||
wxMutexLocker locker(BitmapMutex);
|
|
||||||
wxMemoryDC dc;
|
wxMemoryDC dc;
|
||||||
dc.SelectObject(*backbuffer);
|
dc.SelectObject(*backbuffer);
|
||||||
dc.BeginDrawing();
|
dc.BeginDrawing();
|
||||||
|
@ -648,7 +274,7 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) {
|
||||||
dc.SetLogicalFunction(wxINVERT);
|
dc.SetLogicalFunction(wxINVERT);
|
||||||
|
|
||||||
// Draw frame
|
// Draw frame
|
||||||
dc.DrawBitmap(*curFrame,0,0);
|
dc.DrawBitmap(GetFrame(frame_n),0,0);
|
||||||
|
|
||||||
// Current position info
|
// Current position info
|
||||||
if (x >= 0 && x < w && y >= 0 && y < h) {
|
if (x >= 0 && x < w && y >= 0 && y < h) {
|
||||||
|
@ -703,14 +329,7 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) {
|
||||||
void VideoDisplay::OnMouseLeave(wxMouseEvent& event) {
|
void VideoDisplay::OnMouseLeave(wxMouseEvent& event) {
|
||||||
if (IsPlaying) return;
|
if (IsPlaying) return;
|
||||||
|
|
||||||
// Refresh display
|
RefreshVideo();
|
||||||
{
|
|
||||||
wxMutexLocker locker(BitmapMutex);
|
|
||||||
wxClientDC dc(this);
|
|
||||||
dc.BeginDrawing();
|
|
||||||
dc.DrawBitmap(*curFrame,0,0);
|
|
||||||
dc.EndDrawing();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -724,10 +343,14 @@ void VideoDisplay::JumpToFrame(int n) {
|
||||||
if (IsPlaying && n != PlayNextFrame) return;
|
if (IsPlaying && n != PlayNextFrame) return;
|
||||||
|
|
||||||
// Set frame
|
// Set frame
|
||||||
if (frame_n != n) GetFrame(n);
|
GetFrame(n);
|
||||||
|
|
||||||
|
// Display
|
||||||
|
RefreshVideo();
|
||||||
|
UpdatePositionDisplay();
|
||||||
|
|
||||||
// Update slider
|
// Update slider
|
||||||
if (ControlSlider) ControlSlider->SetValue(n);
|
ControlSlider->SetValue(n);
|
||||||
|
|
||||||
// Update grid
|
// Update grid
|
||||||
if (!IsPlaying && Options.AsBool(_T("Highlight subs in frame"))) grid->UpdateRowColours();
|
if (!IsPlaying && Options.AsBool(_T("Highlight subs in frame"))) grid->UpdateRowColours();
|
||||||
|
@ -744,13 +367,11 @@ void VideoDisplay::JumpToTime(int ms) {
|
||||||
///////////////////
|
///////////////////
|
||||||
// Sets zoom level
|
// Sets zoom level
|
||||||
void VideoDisplay::SetZoom(double value) {
|
void VideoDisplay::SetZoom(double value) {
|
||||||
if (value != zoom) {
|
if (provider) {
|
||||||
zoom = value;
|
provider->SetZoom(value);
|
||||||
if (loaded) {
|
UpdateSize();
|
||||||
OpenAVSSubs();
|
RefreshVideo();
|
||||||
RefreshVideo();
|
GetParent()->Layout();
|
||||||
GetParent()->Layout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,15 +389,17 @@ void VideoDisplay::SetZoomPos(int value) {
|
||||||
///////////////////
|
///////////////////
|
||||||
// Sets zoom level
|
// Sets zoom level
|
||||||
void VideoDisplay::SetAspectRatio(int value) {
|
void VideoDisplay::SetAspectRatio(int value) {
|
||||||
if (value != arType) {
|
if (provider) {
|
||||||
arType = value;
|
if (value == 0)
|
||||||
if (loaded) {
|
provider->SetDAR((float)provider->GetSourceWidth()/(float)provider->GetSourceHeight());
|
||||||
//GetParent()->Freeze();
|
else if (value == 1)
|
||||||
OpenAVSSubs();
|
provider->SetDAR(4.0/3.0);
|
||||||
RefreshVideo();
|
else if (value == 2)
|
||||||
GetParent()->Layout();
|
provider->SetDAR(16.0/9.0);
|
||||||
//GetParent()->Thaw();
|
|
||||||
}
|
UpdateSize();
|
||||||
|
RefreshVideo();
|
||||||
|
GetParent()->Layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,21 +477,11 @@ void VideoDisplay::UpdateSubsRelativeTime() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Locks/unlocks updating
|
|
||||||
void VideoDisplay::Locked(bool state) {
|
|
||||||
bool oldState = isLocked;
|
|
||||||
isLocked = state;
|
|
||||||
if (loaded && oldState == true && isLocked == false) RefreshVideo();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// Copy to clipboard
|
// Copy to clipboard
|
||||||
void VideoDisplay::OnCopyToClipboard(wxCommandEvent &event) {
|
void VideoDisplay::OnCopyToClipboard(wxCommandEvent &event) {
|
||||||
if (wxTheClipboard->Open()) {
|
if (wxTheClipboard->Open()) {
|
||||||
wxMutexLocker locker(BitmapMutex);
|
wxTheClipboard->SetData(new wxBitmapDataObject(GetFrame(frame_n)));
|
||||||
wxTheClipboard->SetData(new wxBitmapDataObject(*curFrame));
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -892,7 +505,7 @@ void VideoDisplay::SaveSnapshot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
curFrame->ConvertToImage().SaveFile(path,wxBITMAP_TYPE_PNG);
|
GetFrame(frame_n).ConvertToImage().SaveFile(path,wxBITMAP_TYPE_PNG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -910,152 +523,24 @@ void VideoDisplay::OnCopyCoords(wxCommandEvent &event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////
|
|
||||||
// Get VSFilter filename
|
|
||||||
wxString VideoDisplay::GetVSFilter() {
|
|
||||||
if (VSFilterPath.IsEmpty()) {
|
|
||||||
wxFileName vsfilterPath(AegisubApp::folderName + _T("vsfilter.dll"));
|
|
||||||
if (vsfilterPath.FileExists()) {
|
|
||||||
VSFilterPath = AegisubApp::folderName + _T("vsfilter.dll");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wxRegKey reg(_T("HKEY_CLASSES_ROOT\\CLSID\\{9852A670-F845-491B-9BE6-EBD841B8A613}\\InprocServer32"));
|
|
||||||
if (reg.Exists()) {
|
|
||||||
reg.QueryValue(_T(""),VSFilterPath);
|
|
||||||
wxFileName file(VSFilterPath);
|
|
||||||
if (!file.FileExists()) VSFilterPath = _T("vsfilter.dll");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VSFilterPath = _T("vsfilter.dll");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return VSFilterPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// Refresh screen
|
// Refresh screen
|
||||||
void VideoDisplay::RefreshVideo(bool force) {
|
void VideoDisplay::RefreshVideo() {
|
||||||
// Prepare
|
// Draw frame
|
||||||
if (isLocked) return;
|
wxClientDC dc(this);
|
||||||
|
dc.BeginDrawing();
|
||||||
// Not loaded
|
dc.DrawBitmap(GetFrame(),0,0);
|
||||||
if (!loaded) {
|
dc.EndDrawing();
|
||||||
wxClientDC dc(this);
|
|
||||||
dc.BeginDrawing();
|
|
||||||
dc.SetBrush(*wxBLUE_BRUSH);
|
|
||||||
dc.DrawRectangle(0,0,w,h);
|
|
||||||
dc.EndDrawing();
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
// Forced
|
|
||||||
if (force) {
|
|
||||||
int n = frame_n;
|
|
||||||
frame_n = -1;
|
|
||||||
OpenAVSSubs();
|
|
||||||
GetFrame(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No frame, try to get one
|
|
||||||
{
|
|
||||||
wxMutexLocker locker(BitmapMutex);
|
|
||||||
if (!curFrame) GetFrame(frame_n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw frame
|
|
||||||
if (curFrame) {
|
|
||||||
wxMutexLocker locker(BitmapMutex);
|
|
||||||
wxClientDC dc(this);
|
|
||||||
dc.BeginDrawing();
|
|
||||||
dc.DrawBitmap(*curFrame,0,0);
|
|
||||||
dc.EndDrawing();
|
|
||||||
//Refresh(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw black
|
|
||||||
else {
|
|
||||||
wxClientDC dc(this);
|
|
||||||
dc.BeginDrawing();
|
|
||||||
dc.Clear();
|
|
||||||
dc.EndDrawing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display
|
|
||||||
UpdatePositionDisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Requests a new frame
|
// Requests a new frame
|
||||||
void VideoDisplay::GetFrame(int n) {
|
wxBitmap VideoDisplay::GetFrame(int n) {
|
||||||
// Make sure it's loaded
|
frame_n = n;
|
||||||
if (!loaded) {
|
|
||||||
//throw _T("Video not loaded");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Threaded mode
|
|
||||||
if (threaded) {
|
|
||||||
nextFrame = n;
|
|
||||||
if (!gettingFrame || framesSkipped > 999999) {
|
|
||||||
framesSkipped = 0;
|
|
||||||
gettingFrame = true;
|
|
||||||
wxThread *thread = new GetFrameThread(this,n);
|
|
||||||
thread->Create();
|
|
||||||
thread->Run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
framesSkipped++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple mode
|
|
||||||
else {
|
|
||||||
GetFrameImage(n);
|
|
||||||
RefreshVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Get frame thread constructor
|
|
||||||
GetFrameThread::GetFrameThread(VideoDisplay *parent,int n)
|
|
||||||
: wxThread(wxTHREAD_DETACHED)
|
|
||||||
{
|
|
||||||
display = parent;
|
|
||||||
image_n = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Get Frame thread entry
|
|
||||||
wxThread::ExitCode GetFrameThread::Entry() {
|
|
||||||
// Get frame
|
|
||||||
display->gettingFrame = true;
|
|
||||||
AviSynthWrapper::AviSynthMutex.Lock();
|
|
||||||
try { display->GetFrameImage(image_n); }
|
|
||||||
catch (...) { }
|
|
||||||
AviSynthWrapper::AviSynthMutex.Unlock();
|
|
||||||
|
|
||||||
// Refresh video
|
|
||||||
//wxMutexGuiEnter();
|
|
||||||
try {
|
|
||||||
display->RefreshVideo();
|
|
||||||
}
|
|
||||||
catch (...) { }
|
|
||||||
//wxMutexGuiLeave();
|
|
||||||
display->gettingFrame = false;
|
|
||||||
|
|
||||||
if (display->nextFrame != image_n) {
|
|
||||||
display->GetFrame(display->nextFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
return provider->GetFrame(n);
|
||||||
Exit();
|
RefreshVideo();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1077,7 +562,6 @@ void VideoDisplay::GetScriptSize(int &sw,int &sh) {
|
||||||
// Width
|
// Width
|
||||||
temp = grid->ass->GetScriptInfo(_T("PlayResX"));
|
temp = grid->ass->GetScriptInfo(_T("PlayResX"));
|
||||||
if (temp == _T("") || !temp.IsNumber()) {
|
if (temp == _T("") || !temp.IsNumber()) {
|
||||||
//sw = orig_w * sh / orig_h;
|
|
||||||
sw = 288;
|
sw = 288;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -42,55 +42,31 @@
|
||||||
// Headers
|
// Headers
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "avisynth_wrap.h"
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "video_provider.h"
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
// Prototypes
|
// Prototypes
|
||||||
class SubtitlesGrid;
|
class SubtitlesGrid;
|
||||||
class VideoDisplay;
|
|
||||||
class VideoSlider;
|
class VideoSlider;
|
||||||
class AudioProvider;
|
class AudioProvider;
|
||||||
class AudioDisplay;
|
class AudioDisplay;
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
|
class VideoProvider;
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// Get Frame thread
|
|
||||||
class GetFrameThread: public wxThread {
|
|
||||||
private:
|
|
||||||
VideoDisplay *display;
|
|
||||||
int image_n;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GetFrameThread(VideoDisplay *parent,int n);
|
|
||||||
wxThread::ExitCode Entry();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
// Main class
|
// Main class
|
||||||
class VideoDisplay: public wxWindow, public AviSynthWrapper {
|
class VideoDisplay: public wxWindow {
|
||||||
friend class GetFrameThread;
|
|
||||||
friend class AudioProvider;
|
friend class AudioProvider;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mouse_x,mouse_y;
|
int mouse_x,mouse_y;
|
||||||
wxBitmap *backbuffer;
|
wxBitmap *backbuffer;
|
||||||
wxString subsName;
|
|
||||||
wxString VSFilterPath;
|
|
||||||
|
|
||||||
PClip sublessVideo;
|
|
||||||
PClip video;
|
|
||||||
double zoom;
|
|
||||||
wxSize origSize;
|
wxSize origSize;
|
||||||
bool isLocked;
|
|
||||||
bool threaded;
|
bool threaded;
|
||||||
bool gettingFrame;
|
|
||||||
int nextFrame;
|
int nextFrame;
|
||||||
int framesSkipped;
|
|
||||||
wxMutex BitmapMutex;
|
|
||||||
|
|
||||||
clock_t PlayTime;
|
clock_t PlayTime;
|
||||||
clock_t StartTime;
|
clock_t StartTime;
|
||||||
|
@ -99,12 +75,10 @@ private:
|
||||||
int EndFrame;
|
int EndFrame;
|
||||||
int PlayNextFrame;
|
int PlayNextFrame;
|
||||||
|
|
||||||
void GetFrameImage(int n);
|
wxBitmap GetFrame(int n);
|
||||||
void GetFrame(int n);
|
wxBitmap GetFrame() { return GetFrame(frame_n); };
|
||||||
void FrameReady();
|
|
||||||
|
|
||||||
void SetZoom(double value);
|
void UpdateSize();
|
||||||
wxString GetVSFilter();
|
|
||||||
void SaveSnapshot();
|
void SaveSnapshot();
|
||||||
|
|
||||||
void OnPaint(wxPaintEvent& event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
@ -116,20 +90,19 @@ private:
|
||||||
void OnPlayTimer(wxTimerEvent &event);
|
void OnPlayTimer(wxTimerEvent &event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxBitmap *curFrame;
|
VideoProvider *provider;
|
||||||
|
|
||||||
wxArrayInt KeyFrames;
|
wxArrayInt KeyFrames;
|
||||||
SubtitlesGrid *grid;
|
SubtitlesGrid *grid;
|
||||||
wxString videoName;
|
wxString videoName;
|
||||||
int arType;
|
int arType;
|
||||||
int w,h;
|
int w,h;
|
||||||
int orig_w,orig_h;
|
|
||||||
int frame_n;
|
int frame_n;
|
||||||
int length;
|
int length;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
bool IsPlaying;
|
bool IsPlaying;
|
||||||
double fps;
|
double fps;
|
||||||
VideoSlider *ControlSlider;
|
VideoSlider *ControlSlider;
|
||||||
//wxSlider *zoomSlider;
|
|
||||||
wxComboBox *zoomBox;
|
wxComboBox *zoomBox;
|
||||||
wxTextCtrl *PositionDisplay;
|
wxTextCtrl *PositionDisplay;
|
||||||
wxTextCtrl *SubsPosition;
|
wxTextCtrl *SubsPosition;
|
||||||
|
@ -139,21 +112,18 @@ public:
|
||||||
VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr);
|
VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr);
|
||||||
~VideoDisplay();
|
~VideoDisplay();
|
||||||
|
|
||||||
void OpenAVSVideo();
|
|
||||||
void OpenAVSSubs();
|
|
||||||
void PrepareAfterAVS();
|
|
||||||
void SetVideo(const wxString &filename);
|
void SetVideo(const wxString &filename);
|
||||||
void SetSubtitles(const wxString &filename);
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Unload();
|
void Unload();
|
||||||
void JumpToFrame(int n);
|
void JumpToFrame(int n);
|
||||||
void JumpToTime(int ms);
|
void JumpToTime(int ms);
|
||||||
void RefreshVideo(bool force=false);
|
void RefreshSubtitles();
|
||||||
|
void RefreshVideo();
|
||||||
void UpdatePositionDisplay();
|
void UpdatePositionDisplay();
|
||||||
void SetAspectRatio(int type);
|
void SetAspectRatio(int type);
|
||||||
|
void SetZoom(double value);
|
||||||
int GetAspectRatio() { return arType; }
|
int GetAspectRatio() { return arType; }
|
||||||
void SetZoomPos(int pos);
|
void SetZoomPos(int pos);
|
||||||
void Locked(bool state);
|
|
||||||
void UpdateSubsRelativeTime();
|
void UpdateSubsRelativeTime();
|
||||||
void GetScriptSize(int &w,int &h);
|
void GetScriptSize(int &w,int &h);
|
||||||
|
|
||||||
|
|
257
core/video_provider.cpp
Normal file
257
core/video_provider.cpp
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
// Copyright (c) 2006, 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
|
||||||
|
//
|
||||||
|
// Website: http://aegisub.cellosoft.com
|
||||||
|
// Contact: mailto:zeratul@cellosoft.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/msw/registry.h>
|
||||||
|
#include "video_provider.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
|
VideoProvider::VideoProvider(wxString _filename, wxString _subfilename, double _zoom, bool &usedDirectshow, bool mpeg2dec3_priority) {
|
||||||
|
RGB32Video = NULL;
|
||||||
|
SubtitledVideo = NULL;
|
||||||
|
ResizedVideo = NULL;
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
last_fnum = -1;
|
||||||
|
|
||||||
|
subfilename = _subfilename;
|
||||||
|
zoom = _zoom;
|
||||||
|
|
||||||
|
LoadVSFilter();
|
||||||
|
|
||||||
|
RGB32Video = OpenVideo(_filename,usedDirectshow,mpeg2dec3_priority);
|
||||||
|
|
||||||
|
dar = GetSourceWidth()/(double)GetSourceHeight();
|
||||||
|
|
||||||
|
SubtitledVideo = ApplySubtitles(subfilename, RGB32Video);
|
||||||
|
ResizedVideo = ApplyDARZoom(zoom, dar, SubtitledVideo);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoProvider::~VideoProvider() {
|
||||||
|
RGB32Video = NULL;
|
||||||
|
SubtitledVideo = NULL;
|
||||||
|
ResizedVideo = NULL;
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoProvider::RefreshSubtitles() {
|
||||||
|
ResizedVideo = NULL;
|
||||||
|
SubtitledVideo = NULL;
|
||||||
|
|
||||||
|
SubtitledVideo = ApplySubtitles(subfilename, RGB32Video);
|
||||||
|
ResizedVideo = ApplyDARZoom(zoom,dar,SubtitledVideo);
|
||||||
|
GetFrame(last_fnum,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoProvider::SetDAR(double _dar) {
|
||||||
|
dar = _dar;
|
||||||
|
ResizedVideo = NULL;
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
ResizedVideo = ApplyDARZoom(zoom,dar,SubtitledVideo);
|
||||||
|
GetFrame(last_fnum,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoProvider::SetZoom(double _zoom) {
|
||||||
|
zoom = _zoom;
|
||||||
|
ResizedVideo = NULL;
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
ResizedVideo = ApplyDARZoom(zoom,dar,SubtitledVideo);
|
||||||
|
GetFrame(last_fnum,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PClip VideoProvider::OpenVideo(wxString _filename, bool &usedDirectshow, bool mpeg2dec3_priority) {
|
||||||
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
AVSValue script;
|
||||||
|
|
||||||
|
usedDirectshow = false;
|
||||||
|
|
||||||
|
wxString extension = _filename.Right(4);
|
||||||
|
extension.LowerCase();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Prepare filename
|
||||||
|
char *videoFilename = env->SaveString(_filename.mb_str(wxConvLocal));
|
||||||
|
|
||||||
|
// Load depending on extension
|
||||||
|
if (extension == _T(".avs")) {
|
||||||
|
script = env->Invoke("Import", videoFilename);
|
||||||
|
} else if (extension == _T(".avi")) {
|
||||||
|
try {
|
||||||
|
const char *argnames[2] = { 0, "audio" };
|
||||||
|
AVSValue args[2] = { videoFilename, false };
|
||||||
|
script = env->Invoke("AviSource", AVSValue(args,2), argnames);
|
||||||
|
//fix me, check for video?
|
||||||
|
} catch (AvisynthError &) {
|
||||||
|
goto directshowOpen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (extension == _T(".d2v") && env->FunctionExists("mpeg2dec3_Mpeg2Source") && mpeg2dec3_priority) //prefer mpeg2dec3
|
||||||
|
script = env->Invoke("mpeg2dec3_Mpeg2Source", videoFilename);
|
||||||
|
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) //try other mpeg2source
|
||||||
|
script = env->Invoke("Mpeg2Source", videoFilename);
|
||||||
|
else {
|
||||||
|
directshowOpen:
|
||||||
|
|
||||||
|
if (env->FunctionExists("DirectShowSource")) {
|
||||||
|
const char *argnames[3] = { 0, "video", "audio" };
|
||||||
|
AVSValue args[3] = { videoFilename, true, false };
|
||||||
|
script = env->Invoke("DirectShowSource", AVSValue(args,3), argnames);
|
||||||
|
usedDirectshow = true;
|
||||||
|
} else
|
||||||
|
throw AvisynthError("No function suitable for opening the video found");
|
||||||
|
}
|
||||||
|
} catch (AvisynthError &err) {
|
||||||
|
throw _T("AviSynth error: ") + wxString(err.msg,wxConvLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!script.AsClip()->GetVideoInfo().HasVideo())
|
||||||
|
throw _T("No usable video found in ") + _filename;
|
||||||
|
|
||||||
|
// Convert to RGB32
|
||||||
|
script = env->Invoke("ConvertToRGB32", script);
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
return (env->Invoke("InternalCache", script)).AsClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
PClip VideoProvider::ApplySubtitles(wxString _filename, PClip videosource) {
|
||||||
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
|
||||||
|
// Insert subs
|
||||||
|
AVSValue script;
|
||||||
|
char temp[512];
|
||||||
|
strcpy(temp,_filename.mb_str(wxConvLocal));
|
||||||
|
AVSValue args[2] = { videosource, temp };
|
||||||
|
|
||||||
|
try {
|
||||||
|
script = env->Invoke("TextSub", AVSValue(args,2));
|
||||||
|
} catch (AvisynthError &err) {
|
||||||
|
throw _T("AviSynth error: ") + wxString(err.msg,wxConvLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
return (env->Invoke("InternalCache", script)).AsClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
PClip VideoProvider::ApplyDARZoom(double _zoom, double _dar, PClip videosource) {
|
||||||
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
|
||||||
|
AVSValue script;
|
||||||
|
VideoInfo vil = videosource->GetVideoInfo();
|
||||||
|
|
||||||
|
int w = vil.height * _zoom * _dar;
|
||||||
|
int h = vil.height * _zoom;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Resize
|
||||||
|
if (!env->FunctionExists(Options.AsText(_T("Video resizer")).mb_str(wxConvLocal)))
|
||||||
|
throw AvisynthError("Selected resizer doesn't exist");
|
||||||
|
|
||||||
|
AVSValue args[3] = { videosource, w, h };
|
||||||
|
script = env->Invoke(Options.AsText(_T("Video resizer")).mb_str(wxConvLocal), AVSValue(args,3));
|
||||||
|
} catch (AvisynthError &err) {
|
||||||
|
throw _T("AviSynth error: ") + wxString(err.msg,wxConvLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
vi = script.AsClip()->GetVideoInfo();
|
||||||
|
|
||||||
|
return (env->Invoke("InternalCache",script)).AsClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxBitmap VideoProvider::GetFrame(int n, bool force) {
|
||||||
|
if (n != last_fnum || force) {
|
||||||
|
|
||||||
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
|
||||||
|
PVideoFrame frame = ResizedVideo->GetFrame(n,env);
|
||||||
|
|
||||||
|
//will fail if not rgb32
|
||||||
|
if (!data)
|
||||||
|
data = new unsigned char[vi.width*vi.height*vi.BitsPerPixel()/8];
|
||||||
|
|
||||||
|
unsigned char* dst = data+(vi.width*(vi.height-1)*vi.BitsPerPixel()/8);
|
||||||
|
int rs = vi.RowSize();
|
||||||
|
const unsigned char* src = frame->GetReadPtr();
|
||||||
|
int srcpitch = frame->GetPitch();
|
||||||
|
|
||||||
|
for (int i = 0; i < vi.height; i++) {
|
||||||
|
memcpy(dst,src,rs);
|
||||||
|
src+=srcpitch;
|
||||||
|
dst-=rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_frame = wxBitmap((const char*)data, vi.width, vi.height, vi.BitsPerPixel());
|
||||||
|
last_fnum = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxBitmap(last_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoProvider::LoadVSFilter() {
|
||||||
|
// Loading an avisynth plugin multiple times does almost nothing
|
||||||
|
|
||||||
|
wxFileName vsfilterPath(AegisubApp::folderName + _T("vsfilter.dll"));
|
||||||
|
|
||||||
|
if (vsfilterPath.FileExists())
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(vsfilterPath.GetFullPath().mb_str(wxConvLocal)));
|
||||||
|
else {
|
||||||
|
wxRegKey reg(_T("HKEY_CLASSES_ROOT\\CLSID\\{9852A670-F845-491B-9BE6-EBD841B8A613}\\InprocServer32"));
|
||||||
|
if (reg.Exists()) {
|
||||||
|
wxString fn;
|
||||||
|
reg.QueryValue(_T(""),fn);
|
||||||
|
|
||||||
|
vsfilterPath = fn;
|
||||||
|
|
||||||
|
if (vsfilterPath.FileExists()) {
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(vsfilterPath.GetFullPath().mb_str(wxConvLocal)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsfilterPath = _T("vsfilter.dll");
|
||||||
|
} else if (vsfilterPath.FileExists())
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(vsfilterPath.GetFullPath().mb_str(wxConvLocal)));
|
||||||
|
else if (!env->FunctionExists("TextSub"))
|
||||||
|
throw _T("Couldn't locate VSFilter");
|
||||||
|
}
|
||||||
|
}
|
100
core/video_provider.h
Normal file
100
core/video_provider.h
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// Copyright (c) 2006, 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
|
||||||
|
//
|
||||||
|
// Website: http://aegisub.cellosoft.com
|
||||||
|
// Contact: mailto:zeratul@cellosoft.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VIDEO_PROVIDER_H
|
||||||
|
#define VIDEO_PROVIDER_H
|
||||||
|
|
||||||
|
#include "avisynth_wrap.h"
|
||||||
|
|
||||||
|
/*class GetFrameVPThread: public wxThread {
|
||||||
|
private:
|
||||||
|
int getting_n;
|
||||||
|
int current_n;
|
||||||
|
|
||||||
|
PClip video;
|
||||||
|
|
||||||
|
wxThread::ExitCode Entry();
|
||||||
|
public:
|
||||||
|
void GetFrame(int n);
|
||||||
|
GetFrameVPThread(PClip clip);
|
||||||
|
};*/
|
||||||
|
|
||||||
|
class VideoProvider: public AviSynthWrapper {
|
||||||
|
private:
|
||||||
|
VideoInfo vi;
|
||||||
|
|
||||||
|
wxString subfilename;
|
||||||
|
|
||||||
|
int last_fnum;
|
||||||
|
|
||||||
|
unsigned char* data;
|
||||||
|
wxBitmap last_frame;
|
||||||
|
|
||||||
|
double dar;
|
||||||
|
double zoom;
|
||||||
|
|
||||||
|
PClip RGB32Video;
|
||||||
|
PClip SubtitledVideo;
|
||||||
|
PClip ResizedVideo;
|
||||||
|
|
||||||
|
PClip OpenVideo(wxString _filename, bool &usedDirectshow, bool mpeg2dec3_priority = true);
|
||||||
|
PClip ApplySubtitles(wxString _filename, PClip videosource);
|
||||||
|
PClip ApplyDARZoom(double _zoom, double _dar, PClip videosource);
|
||||||
|
wxBitmap GetFrame(int n, bool force);
|
||||||
|
void LoadVSFilter();
|
||||||
|
|
||||||
|
public:
|
||||||
|
VideoProvider(wxString _filename, wxString _subfilename, double _zoom, bool &usedDirectshow, bool mpeg2dec3_priority = true);
|
||||||
|
~VideoProvider();
|
||||||
|
|
||||||
|
void RefreshSubtitles();
|
||||||
|
void SetDAR(double _dar);
|
||||||
|
void SetZoom(double _zoom);
|
||||||
|
|
||||||
|
wxBitmap GetFrame(int n) { return GetFrame(n,false); };
|
||||||
|
|
||||||
|
// properties
|
||||||
|
int GetPosition() { return last_fnum; };
|
||||||
|
int GetFrameCount() { return vi.num_frames; };
|
||||||
|
double GetFPS() { return (double)vi.fps_numerator/(double)vi.fps_denominator; };
|
||||||
|
|
||||||
|
int GetWidth() { return vi.width; };
|
||||||
|
int GetHeight() { return vi.height; };
|
||||||
|
|
||||||
|
int GetSourceWidth() { return RGB32Video->GetVideoInfo().width; };
|
||||||
|
int GetSourceHeight() { return RGB32Video->GetVideoInfo().height; };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue